I am working on a small application that is meant to call some (really diverse) functions which are sadly out of my control and designed in such a way that I have no clue when the proper user action is done. In particular some of these spawn a thread to do their work in, which ends up dying at some point in the future. So some are implemented sync, some are implemented asynchronous, and my code does not know which of those it will be.
The only purpose of my application is to launch these tasks and terminate upon completion. Since the purpose is automation, I anticipate it being called 100s of times from batchfiles in a matter of moments, so I do not wish the process to linger any longer than absolutely possible.
Since I have no signal I can wait for, ExitThread() on my primary thread seems to be the way to go, so that any threads spawned by the foreign code will end up killing the process when they terminate.
So now to get to my actual issue mentioned in the title. 🙂 In order to get the proper interfaces for my jig, I need to mess around with some COM functions. SHParseDisplayName, IShellFolder::GetUIObjectOf and a bunch of others. But long after I am done with these interfaces and have released them, these threads remain present. Even after I called CoUninitialize().
When inspecting my process using Process Explorer, the majority of these threads seem to have ntdll.dll@EtwTraceMessageVa as the entry point, and are stuck in ntdll.dll!ZwAlpcSendWaitReceivePort+0xa. Obviously, randomly terminating threads using TerminateThread is not an option here.
How can I get COM to terminate those threads when I am done with using it? I am using W7 x64 to develop on.
I figured out the problem, and it was an obvious case of all the documentation being somewhere but not where you are looking, and a somewhat related subject has had a blog post on this issue which brought me to the missing piece.
My app pops up an
IContextMenuof a file (hence noShellExecutein my code), and then allows one to invoke a command. However, some verbs likepropertiesare the oddballs that my question was about: they spawn another thread and give no notification or obvious way to block it.Using SHSetExplorerInstance as mentioned in the linked post fixed my problems. 🙂