1

App1.exe、App2.exe、App3.exe の 3 つのプログラムがあります。それぞれは互いに独立して実行できますが、App2.exe は ShellExecuteEx を使用して App3.exe を実行し、App1.exe は ShellExecuteEx を使用して App2.exe を実行する場合があります (これにより、App3 が実行される場合があります)。App3 にはオプションのコマンド ライン パラメーターがあり、使用すると GUI は表示されませんが、自動的に出力ファイルを生成して閉じます。App2 がコマンド ライン パラメーターを渡して App3 を実行すると問題なく動作しますが、App1 がコマンド ライン パラメーターを渡して App3 を実行する App2 を実行すると、App3 の ShellExecuteEx は true を返しますが、GUI は表示され、出力ファイルは作成されません。
なぜこれが起こるのか分かりますか?Windows XP では動作しますが、Vista または 7 では動作しません。CreateProcess() も使用してみましたが、同じ結果が得られました。3 つのアプリはすべて同じフォルダーにあります。

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 );
4

1 に答える 1

4

App2 が App3 を実行すると、App2 が直接実行されたか App1 によって実行されたかに関係なく、App3 はまったく同じ方法で実行されます。したがって、App2 を実行している App1 が、App2 によって App3 が実行される方法に影響を与える可能性はありません。

影響を受ける可能性があるのは、 App2の最初の作業ディレクトリ、つまり App3 の最初の作業ディレクトリですそのため、パラメーター値だけでなく、.exe パスにも常に絶対パスを使用する必要があります。SHELLEXECUTEINFO.lpDirectoryフィールドを使用して初期作業ディレクトリを指定することも検討する必要があります。アプリが作業中に間違ったディレクトリを参照する可能性がないようにするためです。

そうは言っても、それでも同じ問題が発生する場合は、App3 が受け取った実際のコマンドライン パラメーター ( MessageBox()、OutputDebugString()、ファイルなど) を出力することをお勧めします。予想とは異なるものを受け取っているか、パラメーターを正しく解析していない可能性があります。

Sleep()+GetExitCodeProcess()最後に、余談ですが、ループを単一の呼び出しWaitForSingleObject()(またはMsgWaitForMultipleObjects()待機中にメッセージ ループを実行する必要がある場合) に置き換え、GetExitCodeProcess()その後、必要に応じて最終結果を取得するために 1 回呼び出すことができます。

if ShellExecuteEx( @exInfo ) then
begin
  if WaitForSingleObject(exinfo.hProcess, INFINITE) = WAIT_OBJECT_0 then
    GetExitCodeProcess( exinfo.hProcess, exitcode );
  CloseHandle( exinfo.hProcess );
end;
于 2013-08-23T21:02:03.807 に答える