Reputation: 10037
I'm trying to open a *.jpg
file with CreateProcess()
and I want CreateProcess()
to behave exactly the same as when opening the *.jpg
with ShellExecute()
.
So I first use FindExecutable()
to get the viewer application for the *.jpg
file, then I concatenate the viewer application's path and the path to the *.jpg
file, adding quotes to make sure it works with paths that have spaces in them.
However, the result is not the same: On my system *.jpg
files are associated with an application that has a lightweight viewer mode and a more sophisticated editor mode. When I use ShellExecute()
to open the file (or double-click on it in Explorer), the viewer application opens in the lightweight viewer mode. When I use CreateProcess()
as described above, however, the viewer application shows the *.jpg
file as well but it opens in editor mode.
So ShellExecute()
must be doing something else that causes the viewer application to behave like it does but I don't know what. Any ideas what might be missing to make CreateProcess()
behave exactly like ShellExecute()
?
This is what the code looks like currently:
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));
memset(&siStartInfo, 0, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
Upvotes: 0
Views: 832
Reputation: 101569
ShellExecute
uses CreateProcess
internally but before it gets there it does many other things.
This blog post by Raymond Chen provides a hint:
The FindExecutable function comes from 16-bit Windows, and back in those days, there were no context menu shell extensions or custom drop targets. (There was DDE, but that’s okay, because programs still have to register an executable to be used in the fallback case when nobody responds to the DDE message.)
...
Newer applications shouldn’t be using FindExecutable anyway, seeing as the handler for a file type may not even be an executable.
A IContextMenu
based shell extension could be the default and if it is, it can do anything and ShellExecute
just tells the extension to invoke the command. This is not done if SEE_MASK_INVOKEIDLIST
is not specified?
A classic static verb in the registry can have IExecuteCommand
and/or drop target handlers that also perform the actual execution.
If neither of the above are true, ShellExecute
will look for DDE registration and if found it will try to use DDE.
If all else fails, ShellExecute
will use CreateProcess
to invoke the command string after substituting the %1 values.
Even if you emulate all of this (including all the undocumented details and compatibility workarounds) you still have to call ShellExecute
if the command resolves to a executable that requires UAC elevation.
Just figuring out which verb is the true default is hard enough, I suggest that you just use ShellExecute
and let the shell handle the rest.
If you are just curious, you can look at the resulting command line in Task Manager or Process Explorer to see if a custom handler simply adds a special parameter.
Upvotes: 3