MSDN has this tip:
Because ShellExecuteEx can delegate execution to Shell extensions (data sources, context menu handlers, verb implementations) that are activated using the Component Object Model (COM), COM must be initialized before ShellExecuteEx is called. Some Shell extensions require a single-threaded COM (STA) type of apartment. In this case, COM should be initialized as shown below:
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
There are instances in which ShellExecuteEx does not use one of these types of shell extensions, and these instances do not require COM initialization. However, it is good practice to always initialize COM before using this function.
(In Delphi, of course, you replace the first parameter with nil and use or for the bitwise operation.)
Raymond Chen recently wrote about the consequences of this wrong . A concrete example is that a function may fail with the error code Error_Access_Denied .
This is the only potential threading problem that I see in your code. The following are other things that happened to me when I read your code, although they have nothing to do with multithreading (and don't even have much to do with Indy).
You have a special way to wait for the program to finish. You repeatedly wait 50 milliseconds at a time, but if the process is not finished, you are not doing anything, but wait again. Describe your intention more accurately by specifying Infinite for the timeout.
The function always returns True . If there is no useful return value, you should simply make it a procedure so that there is no return value. Do not confuse the caller with useless information. If you intend to save it as a function, use the Delphi native Boolean type instead of the Windows Bool compatibility type for the return type.
I am a little afraid of the idea of ββa server running user interactive programs after receiving network messages.
Note that MSDN says that you cannot get the process descriptor. There are times when ShellExecuteEx can serve your request without creating a new process, so you have nothing to wait for.
The user may end up using the program for a while, and your server will wait all this time. I wonder if it's worth the wait. Will the client wait for a response from the server?