• ベストアンサー

外部exe呼び出しの方法 ShellExecuteEx, System...

VC++6での質問す。 ◆やりたいこと◆ (1)内部から外部exeを引数ありで呼び出し、処理をさせます。 (2)その外部exeの結果コードを内部的に受け取り、エラー処理させます。 (3)外部exeの処理実行中は、できればDOS窓を非表示にさせます。 system()呼び出しは最も簡単なのですが、(3)が上手くできませんでした。 ◆やってみた方法◆ こちらの過去質問も参考に見よう見まねでShellExecuteExを使ってやってみようとしました。 ↓ SHELLEXECUTEINFO sei; DWORD dwRC; LPVOID msg; BOOL res; ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO)); sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.nShow = SW_HIDE; sei.lpVerb = (LPCTSTR)cmd; // cmdの中は、"hoge.exe param1 param2" res=ShellExecuteEx( &sei ); WaitForSingleObject( sei.hProcess, INFINITE ); GetExitCodeProcess( sei.hProcess, &dwRC ); CloseHandle(sei.hProcess); if(res != FALSE){ MessageBox( "OK", "result", MB_OK ); }else{ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwRC, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL ); MessageBox( msg, "result", MB_OK | MB_ICONERROR ); LocalFree(msg); } 以上で実行しようとすると、 「指定されたファイルに対してこの操作を行うアプリケーションが関連付けられていません・・・」 のエラーになってしまいます。 どのように改善していけばよいでしょうか。 ソースはあちこちのものをミックスして書いていて、半分意味も分からずで、とんでもないことをしているかも知れません(VCは初心者で、ハンドルとかクラス、プロセスとかの知識に乏しいです) また、まったく別で良い方法(CreateProcessの方が簡単だとか)があれば、よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • valvelde
  • ベストアンサー率35% (46/129)
回答No.2

SHELLEXECUTEINFO構造体に設定する値が間違っています。 この場合は下記の値を設定します。 sei.lpVerb = "open" sei.lpFile = "hoge.exe" sei.lpParameters = "param1 param2" あとGetExitCodeProcess関数を使用するためにPROCESS_QUERY_INFORMATIONアクセス権を割り当てる必要があるのでOpenProcess関数を使用してアクセス権を割り当ててください。

supob
質問者

お礼

ご回答ありがとうございました。遅くなりすみません。 >>あとGetExitCodeProcess関数を使用するためにPROCESS_QUERY_INFORMATIONアクセス権を… この辺の用語や意味が理解できておらず、その辺りから勉強しないといけないかなと思っています。 とりあえず、CreateProcessのコードを他のソースから見様見まねで書いてみて、なんとなく動いているようです。(↑) 何かこちらも間違いがあれば、指摘お願いします。

supob
質問者

補足

最終的に、CreateProcess()関数を使って、次のようにしています。 DWORD xxxDlg::ExecCmd(void* cmd){ STARTUPINFO si; PROCESS_INFORMATION pi; DWORD dwSysRC,dwExitCode; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; CreateProcess(NULL, (char*)cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); WaitForSingleObject(pi.hProcess, INFINITE); dwSysRC=GetLastError(); // CreateProcess関数としての戻り値 if(dwSysRC != 0){ SystemErrMsg(dwSysRC); // ユーザ作成関数 return(-1); } GetExitCodeProcess(pi.hProcess, &dwExitCode); //実行したコマンドそのものが返す戻り値 CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return(dwExitCode); }

その他の回答 (1)

回答No.1

ShellExecute() の使い方を誤っています。 この関数は exe を指定して起動するのではなく、 指定したファイルに関連付けてあるアプリを起動させるというものです。 たとえば aaaaa.txt を指定して実行するとメモ帳が立ち上がり aaaaa.txt を読み込む。また bbbb.xls を指定して実行すると Excel が立ち上がり bbbb.txt を読み込む。そういった動作になります。関連付けがなされてない場合はエラーになります(質問者さんの場合) CreateProcess() を使うべきですが、パラメータの指定が面倒くさいので WinExec() を使ったらいかがでしょう。WinExecは互換性のために残されている関数なので薦めるべきではないかもしれませんが…(^^;

supob
質問者

お礼

>>この関数は exe を指定して起動するのではなく、 >>指定したファイルに関連付けてあるアプリを起動させるというものです。 分かりやすいご説明ありがとうございました。すぐに納得できました。 私自身が、この辺のワンポイントがすぐに分かれば良いのですが、 どうもVCなどのヘルプ(特に英文)ではこの辺の”つかみ”が私のような初心者には分かり難い所です。 何か良いヘルプサイトなど、ご紹介頂ければと思います。 ・・・ ということで、本題の方ですが、CreateProcessにて、 ここから呼び出すexe(lpCommandLine)そのものの戻り値は、CreateProcessの戻り値ではないですよね。 何かの引数(構造体)に入れられて戻ってくるとは思うのですが。もう少し調べてみたいと思います。 取り急ぎ、ありがとうございました。

supob
質問者

補足

早速のご回答ありがとうございました。 WinExec()を試してみたのですが、第2引数に WinExec((const char*)cmd,SW_HIDE); と指定することで、DOS窓を表示しないようには出来たのですが、 cmdで実行するexeそのものが返す戻り値を受けることができませんでした。 CreateProcessに挑戦でしょうか・・・