Question

I have 3 programs, App1.exe, App2.exe, and App3.exe. Each can be run independently from one another, but App2.exe may run App3.exe using ShellExecuteEx, and App1.exe may run App2.exe using ShellExecuteEx (which in turn may run App3). App3 has optional command line parameters when if used the GUI will not show but will automatically generate an output file and close. When App2 runs App3 passing in the command line parameters it works just fine, but when App1 runs App2 which runs App3 passing in the command line parameters, the ShellExecuteEx of App3 returns true but the GUI shows up and does not create the output file.
Do you have any idea why this would happen? It does work on Windows XP, but it doesn't on Vista or 7. I also tried using CreateProcess() which gave the same result. All 3 apps are in the same folder.

FillChar( exInfo, Sizeof(exInfo), 0 );
with exInfo do
begin
  cbSize:= Sizeof( exInfo );
  fMask := SEE_MASK_NOCLOSEPROCESS;
  lpVerb:= 'open';
  lpFile:= PChar('App3.exe');
  lpParameters := PChar('/Param1 Param2 "' + folderpath + 'outputfile.txt"');
  nShow := SW_HIDE;
end;
if ShellExecuteEx( @exInfo ) then
begin
  repeat
    Sleep( 500 );
    GetExitCodeProcess( exinfo.hProcess, exitcode )
  until (exitcode <> STILL_ACTIVE);
end;
CloseHandle( exinfo.hProcess );
Was it helpful?

Solution

When App2 runs App3, App3 gets run the exact same way regardless of whether App2 was run directly or by App1. So there is no way that App1 running App2 could be affecting how App3 gets run by App2.

What CAN be affected is App2's initial working directory, and thus App3's initial working directory. So you should always use absolute paths, not just for parameter values but also for the .exe paths as well. You should also consider using the SHELLEXECUTEINFO.lpDirectory field to specify an initial working directory. Just so there is no possibility that your apps are looking in the wrong directories while doing their work.

That being said, if you still have the same problem, then I suggest you have App3 output the actual command-line parameters that it received (MessageBox(), OutputDebugString(), a file, etc). It might be receiving something different than you are expecting, or it may be parsing the parameters incorrectly.

Lastly, on a side note, you can replace your Sleep()+GetExitCodeProcess() loop with a single call to WaitForSingleObject() (or MsgWaitForMultipleObjects() if you need to run a message loop while waiting), and then call GetExitCodeProcess() once afterwards to get the final result, if needed:

if ShellExecuteEx( @exInfo ) then
begin
  if WaitForSingleObject(exinfo.hProcess, INFINITE) = WAIT_OBJECT_0 then
    GetExitCodeProcess( exinfo.hProcess, exitcode );
  CloseHandle( exinfo.hProcess );
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top