Reconnect to Process Started Via COM - c++

First, I'd like to note that I need to use the COM/OLE2 APIs, the low level stuff, the stuff you can put in a C Windows Console program. I can't use MFC. I can't use .NET.
My question is:
Given the following code:
CLSID clsid;
HRESULT hr;
hr = CLSIDFromProgID(L"InternetExplorer.Application", &clsid);
assert(SUCCEEDED(hr));
hr = CoCreateInstance(clsid,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IDispatch,
(void **)&(iePtr_));
assert(SUCCEEDED(hr));
Is there a way to write some information to the disk so that I can reconnect to the same instance of IE later on? Basically can "iePtr_" be stringified for later reconstitution by some other process?
Thanks.
---- added later------
The broader problem I am trying to solve is that I want to start an AutoCAD application, load some data into it, and then leave it running for my client to interact with. Later he will go back to my application and I want to reconnect to the same AutoCAD session and feed it more data.
Now, I full well realize I can keep the IDispatch pointer in memory in my application and I'll be able to continue to interact with the same AutoCAD process. That's my fallback position.
However, I use a "wrapper" program to do my COM stuff. So the wrapper is transient. My main application starts the wrapper, then the wrapper communicates, and then exits. I just want subsequent wrapper processes to be able to reconnect to the same AutoCAD process.
Why use a wrapper? Here's the working reason: My main application is a 32-bit application, but I can use a 64-bit wrapper and communicate with 64-bit AutoCAD. I need to be able to communicate with 64-bit AutoCAD and can probably not port my main application easily (500K+ lines of C++) vs. my wrapper program (couple hundred lines).

If the application registered itself in the Running Object Table, you can use the GetActiveObject function to get a reference to the application object.
IUnknown *pUnknown;
hr = GetActiveObject(clsid, NULL, &pUnknown);
assert(SUCCEEDED(hr));
hr = pUnknown->QueryInterface(IID_IDispatch, (void **)&(iePtr_));
assert(SUCCEEDED(hr));

CoMarshalInterface (and related APIs) can be used to marshal an interface into another thread, process or different PC on the network. I don't know how long you are allowed to wait before completing the marshaling process, but in principal, if the object you are marshaling an interface to has not been closed the marshaling process can be completed later.
Being able to destroy an OLE object and later restore "the same object" is tied into what are called Monikers, and if you (can) understand those then your OLE/COM Juju is powerful indeed.

I'd suggest making the wrapper layer long lived rather than transient, therefore it can easily hold a single reference to the third application.
The wrapper can still appear transient to the client code.
If you make the wrapper a COM singleton then each time you cocreate it, you will get back the same instance.
To ensure the wrapper lives for the lifetime of your client hold a reference from startup to shutdown. This reference does not need to be wired through to other code. All other code simply creates the singleton every time it wants it.

Nope, that's impossible. The whole idea of COM is that the COM server is started transparently and only preserves state until you have stopped using its objects. After you've released the COM objects the COM subsystem is free to completely stop the server and there's no way to recreate the same process. The only way a similar result would be possible is to have a COM object with serialization methods that would permit saving the state into a stream and restoring it from a stream. But even then you would have to CoCreateInstance() again, obtain a new COM object interface pointer and call the restore method of that object.
The pointer you get from CoCreateInstance is only valid for the current process, if you save it on disk and restore later it will become invalid.

Related

Thread marshalling to COM STA library

I am trying to use my own C++ class to interact with a COM library that is STA.
The problem we are trying to solve is that a third party application has the STA attribute set to it. The application then creates the C++ service we created and other services (in our case a WCF service) are modifying elements in the service created by the third party STA attribute application. In essence we have Thread1 coming from STA application who creates the service, then Thread2...N coming from WCF which is not in a STA thread state manipulating data held in the service. The STA application doesn't see the changed data and acts as though nothing happened.
So in order to fix it, I am thinking that I have to ensure that all operations contained in my service need to be guaranteed to run on the same thread. The question I have is how to achieve that.
I will show an example of our current code.
Current Service (every method needs to be called on the same thread that it was initially created on)
MyService::MyService()
{
// creates some objects and maybe some other initializing
// Whatever thread (the STA application in this case) this was
// created on needs to be used on all methods, how?
}
ObjectA MyService::GetObject()
{
return anObject;
}
ObjectB MyService::CreateObjectB()
{
// Do some tasks that eventually create object
object = new ObjectB();
return object;
}
void MyService::SomeVoidFunction()
{
// Do some work
}
I am not sure if I can take advantage of the TPL and do this, or do I need to use ThreadPools or something like that?

win32 SetTimer waitfor TIMERPROC [duplicate]

In this thread (posted about a year ago) there is a discussion of problems that can come with running Word in a non-interactive session. The (quite strong) advice given there is not to do so. In one post it is stated "The Office APIs all assume you are running Office in an interactive session on a desktop, with a monitor, keyboard and mouse and, most importantly, a message pump." I'm not sure what that is. (I've been programming in C# for only about a year; my other programming experience has primarily been with ColdFusion.)
Update:
My program runs through a large number of RTF files to extract two pieces of information used to construct a medical report number. Rather than try and figure out how the formatting instructions in RTF work, I decided to just open them in Word and pull the text out from there (without actually starting the GUI). Occasionally, the program hiccuped in the middle of processing one file, and left a Word thread open attached to that document (I still have to figure out how to shut that one down). When I re-ran the program, of course I got a notification that there was a thread using that file, and did I want to open a read-only copy? When I said Yes, the Word GUI suddenly popped up from nowhere and started processing the files. I was wondering why that happened; but it looks like maybe once the dialog box popped up the message pump started pushing the main GUI to Windows as well?
A message loop is a small piece of code that exists in any native Windows program. It roughly looks like this:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The GetMessage() Win32 API retrieves a message from Windows. Your program typically spends 99.9% of its time there, waiting for Windows to tell it something interesting happened. TranslateMessage() is a helper function that translates keyboard messages. DispatchMessage() ensures that the window procedure is called with the message.
Every GUI enabled .NET program has a message loop, it is started by Application.Run().
The relevance of a message loop to Office is related to COM. Office programs are COM-enabled programs, that's how the Microsoft.Office.Interop classes work. COM takes care of threading on behalf of a COM coclass, it ensures that calls made on a COM interface are always made from the correct thread. Most COM classes have a registry key in the registry that declares their ThreadingModel, by far the most common ones (including Office) use "Apartment". Which means that the only safe way to call an interface method is by making the call from the same thread that created the class object. Or to put it another way: by far most COM classes are not thread-safe.
Every COM enabled thread belongs to a COM apartment. There are two kinds, Single Threaded Apartments (STA) and a Multi Thread Apartment (MTA). An apartment threaded COM class must be created on an STA thread. You can see this back in .NET programs, the entry point of the UI thread of a Windows Forms or WPF program has the [STAThread] attribute. The apartment model for other threads is set by the Thread.SetApartmentState() method.
Large parts of Windows plumbing won't work correctly if the UI thread is not STA. Notably Drag+Drop, the clipboard, Windows dialogs like OpenFileDialog, controls like WebBrowser, UI Automation apps like screen readers. And many COM servers, like Office.
A hard requirement for an STA thread is that it should never block and must pump a message loop. The message loop is important because that's what COM uses to marshal an interface method call from one thread to another. Although .NET makes marshaling calls easy (Control.BeginInvoke or Dispatcher.BeginInvoke for example), it is actually a very tricky thing to do. The thread that executes the call must be in a well-known state. You can't just arbitrarily interrupt a thread and force it to make a method call, that would cause horrible re-entrancy problems. A thread should be "idle", not busy executing any code that is mutating the state of the program.
Perhaps you can see where that leads: yes, when a program is executing the message loop, it is idle. The actual marshaling takes place through a hidden window that COM creates, it uses PostMessage to have the window procedure of that window execute code. On the STA thread. The message loop ensures that this code runs.
The "message pump" is a core part of any Windows program that is responsible for dispatching windowing messages to the various parts of the application. This is the core of Win32 UI programming. Because of its ubiquity, many applications use the message pump to pass messages between different modules, which is why Office applications will break if they are run without any UI.
Wikipedia has a basic description.
John is talking about how the Windows system (and other window based systems - X Window, original Mac OS....) implement asynchronous user interfaces using events via a message system.
Behind the scenes for each application there is a messaging system where each window can send events to other windows or event listeners -- this is implemented by adding a message to the message queue. There is a main loop which always runs looking at this message queue and then dispatching the messages (or events) to the listeners.
The Wikipedia article Message loop in Microsoft Windows shows example code of a basic Windows program -- and as you can see at the most basic level a Windows program is just the "message pump".
So, to pull it all together. The reason a windows program designed to support a UI can't act as a service is because it needs the message loop running all the time to enable UI support. If you implement it as a service as described, it won't be able to process the internal asynchronous event handling.
In COM, a message pump serialises and de-serialises messages sent between apartments. An apartment is a mini process in which COM components can be run. Apartments come in single threaded and free threaded modes. Single threaded apartments are mainly a legacy system for applications of COM components that don't support multi-threading. They were typically used with Visual BASIC (as this did not support multi-threaded code) and legacy applications.
I guess that the message pump requirement for Word stems from either the COM API or parts of the application not being thread safe. Bear in mind that the .NET threading and garbage collection models don't play nicely with COM out of the box. COM has a very simplistic garbage collection mechanism and threading model that requires you to do things the COM way. Using the standard Office PIAs still requires you to explicitly shut down COM object references, so you need to keep track of every COM handle created. The PIAs will also create stuff behind the scenes if you're not careful.
.NET-COM integration is a whole topic all by itself, and there are even books written on the subject. Even using COM APIs for Office from an interactive desktop application requires you to jump through hoops and make sure that references are explicitly released.
Office can be assumed to be thread-unsafe, so you will need a separate instance of Word, Excel or other Office applications for each thread. You would have to incur the starting overhead or maintain a thread pool. A thread pool would have to be meticulously tested to make sure all COM references were correctly released. Even starting and shutting down instances requires you to make sure all references are released correctly. Failure to dot your i's and cross your t's here will result in large numbers of dead COM objects and even whole running instances of Word being leaked.
Wikipedia suggests it means the program's main Event Loop.
I think that this Channel 9 discussion has a nice succinct explanation:
This process of window communication is made possible by the so-called Windows Message Pump. Think of the Message Pump as an entity that enables cooperation between application windows and the desktop.

MFC UI Automation graceful shutdown

Our MFC app hangs during shutdown if any UI Automation client is active (Such as Inspect. Windows Eyes, UI Spy etc.)
The reason is BOOL AFXAPI AfxOleCanExitApp() returns false if any Ole Objects exist. The app then goes into hidden server mode.
I have seen similar posts dealing with Document objects. The general solution is to set the object count to 0, close normally then set the count back in the OnClose of the main frame.
This is a poor solution for UI Automation. It causes memory leaks and invalid objects in the Client app ( Inspect actually crashes after a time).
Has anyone seen a proper way to tell UI clients this server is going away and release all objects?
There is no real good way to shut down graceful. There is no graceful way to stop any server when it is still in use. You can only do necessary cleanup.
You have Connections to you objects. What is graceful if you cut them? You can use CoDisconnectObject for every object. But there is no difference when you terminate the application. Also using this function doesn't reduce the objects lock count! But you can delete the object without getting a crash with an access from the other COM clients.
The draw back: CoDisconnectObject only works for external links. If you have internal COM pointers the object, they are not affected. So those may still use your object...
When you really find every object that has an external connection you can destroy it. And if you have no internal COM-pointers you can delete your objects even with a usage count !=0. But in lots of cases I have other dependent COM-objects that are linked...
The only real good way to terminate gracefully is to stop all applications that use your application as a server first! And exit after this is done... ;)
So if you want to force a shutdown. Disconnect what you can. Free as many resources you know. Than ignore the applications lock count and exit. Memory is freed, even if the debug version will report a leak. Problematic are only other resources (files, mutexes, system objects...) that may need a better handling as closing the application...

How can I address a COM object identified by a given IUnknown* from another process?

I wrote two small C++ applications, one of which is an ActiveX container embedding some ActiveX control. This container application knows the IUnknown* referencing the ActiveX control.
The other application is a client which shall interact with the ActiveX control in the former application. However, I don't know how to get a handle on the control in the client application. Simply transporting the pointer value of the IUnknown* from the server to the client won't work of courses due to independant address spaces.
Is it somehow possible to "duplicate" a handle to some COM object so that the newly created handle can be used by other processes? I'd like to have COM do the RPC work for me. Otherwise, I'd need to do all COM calls in the server application and do all the RPC myself. :-/
You may want to look at RPC in general, and COM Proxies.
A proxy resides in the address space of the calling process and acts as a surrogate for the remote object. From the perspective of the calling object, the proxy is the object. Typically, the proxy's role is to package the interface parameters for calls to methods in its object interfaces. The proxy packages the parameters into a message buffer and passes the buffer onto the channel, which handles the transport between processes. The proxy is implemented as an aggregate, or composite, object. It contains a system-provided, manager piece called the proxy manager and one or more interface-specific components called interface proxies. The number of interface proxies equals the number of object interfaces that have been exposed to that particular client. To the client complying with the component object model, the proxy appears to be the real object.

How can I perform network IO at the very end of a process' lifetime?

I'm developing a DLL in C++ which needs to write some data via a (previously established) TCP/IP connection using the write() call. To be precise, the DLL should send a little 'Process 12345 is terminating at 2007-09-27 15:30:42, value of i is 131' message over the wire when the process goes down.
Unfortunately, all the ways I know for detecting that the process is ending are apparently too late for any network calls to succeed. In particular, I tried the following approaches and the write() call returned -1 in every case:
Calling write() from the destructor of a global object.
Calling write() from a callback function registered using atexit().
Calling write() from DllMain (in case the reason argument is DLL_PROCESS_DETACH). I know that this is not a safe thing to do, but I'm getting a bit desperate. :-)
I'm aware that a DLL can't detect any process shutdown (it might have been unloaded long before the process terminates) but since the shutdown data which the DLL needs to send depends on other code in the DLL, that's acceptable. I'm basically looking for the latest moment at which I can safely perform network IO.
Does anybody know how to do this?
Consider monitoring the process from a separate watchdog process.
Determining If a Process Has Exited: http://msdn.microsoft.com/en-us/library/y111seb2(v=VS.71).aspx
Tutorial: Managing a Windows Process: http://msdn.microsoft.com/en-us/library/s9tkk4a3(v=VS.71).aspx
Consider to use Windows Job Objects.
You main program (monitoring program, which will use for example send()) can start child process suspended, place it into a Job and then resume. Then it will run in the job object. You can register notification via SetInformationJobObject with JobObjectAssociateCompletionPortInformation. Then you will be notified if in the job will be created some child process and if some process inside of job will be ended. So you will be able to send all what you need from the monitoring process. If you debug a program in Visual Studio it uses also job objects to have control under your process and all child processes which you start.
I successfully use the technique in C++ and in C#. So if you will have some problem with implementation I could post you a code example.
I suggest taking option 3. Just do your DLL loading/unloading properly and you're fine. Calling write() should work, I can't explain why it's not in your case. Is it possible that the call fails for a different reason that is unrelated?
Does it work if you call your DLL function manually from the host app?
Why? Just close the socket. If that's the only close in the program, which by your description it must be, that tells the other end that this end is exiting, and you can send the process ID information at the beginning instead of the end. You shouldn't do anything time-consuming or potentially blocking in an exit hook or static destructor.
Where is Winsock being shut down using WSACleanup? You need to make sure that your I/O completes before this happens.
You should be able to work out if this is happening by placing a breakpoint on the Win32 call in Winsock2.dll. Unload of DLLs is displayed in the output in the debug window.