プロが教える店舗&オフィスのセキュリティ対策術

VC++6での質問す。
◆やりたいこと◆
(1)内部から外部exeを引数ありで呼び出し、処理をさせます。
(2)その外部exeの結果コードを内部的に受け取り、エラー処理させます。
(3)外部exeの処理実行中は、できればDOS窓を非表示にさせます。

system()呼び出しは最も簡単なのですが、(3)が上手くできませんでした。

◆やってみた方法◆
こちらの過去質問も参考に見よう見まねでShellExecuteExを使ってやってみようとしました。

SHELLEXECUTEINFO sei;
DWORDdwRC;
LPVOID msg;
BOOLres;

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の方が簡単だとか)があれば、よろしくお願いします。

A 回答 (2件)

SHELLEXECUTEINFO構造体に設定する値が間違っています。


この場合は下記の値を設定します。
sei.lpVerb = "open"
sei.lpFile = "hoge.exe"
sei.lpParameters = "param1 param2"

あとGetExitCodeProcess関数を使用するためにPROCESS_QUERY_INFORMATIONアクセス権を割り当てる必要があるのでOpenProcess関数を使用してアクセス権を割り当ててください。

この回答への補足

最終的に、CreateProcess()関数を使って、次のようにしています。

DWORD xxxDlg::ExecCmd(void* cmd){

STARTUPINFOsi;
PROCESS_INFORMATIONpi;
DWORDdwSysRC,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);
}

補足日時:2006/03/03 09:57
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。遅くなりすみません。

>>あとGetExitCodeProcess関数を使用するためにPROCESS_QUERY_INFORMATIONアクセス権を…

この辺の用語や意味が理解できておらず、その辺りから勉強しないといけないかなと思っています。

とりあえず、CreateProcessのコードを他のソースから見様見まねで書いてみて、なんとなく動いているようです。(↑)
何かこちらも間違いがあれば、指摘お願いします。

お礼日時:2006/03/03 10:06

ShellExecute() の使い方を誤っています。


この関数は exe を指定して起動するのではなく、
指定したファイルに関連付けてあるアプリを起動させるというものです。

たとえば aaaaa.txt を指定して実行するとメモ帳が立ち上がり aaaaa.txt を読み込む。また bbbb.xls を指定して実行すると Excel が立ち上がり bbbb.txt を読み込む。そういった動作になります。関連付けがなされてない場合はエラーになります(質問者さんの場合)

CreateProcess() を使うべきですが、パラメータの指定が面倒くさいので WinExec() を使ったらいかがでしょう。WinExecは互換性のために残されている関数なので薦めるべきではないかもしれませんが…(^^;

この回答への補足

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

補足日時:2006/02/28 13:52
    • good
    • 0
この回答へのお礼

>>この関数は exe を指定して起動するのではなく、
>>指定したファイルに関連付けてあるアプリを起動させるというものです。

分かりやすいご説明ありがとうございました。すぐに納得できました。

私自身が、この辺のワンポイントがすぐに分かれば良いのですが、
どうもVCなどのヘルプ(特に英文)ではこの辺の”つかみ”が私のような初心者には分かり難い所です。
何か良いヘルプサイトなど、ご紹介頂ければと思います。
・・・

ということで、本題の方ですが、CreateProcessにて、
ここから呼び出すexe(lpCommandLine)そのものの戻り値は、CreateProcessの戻り値ではないですよね。
何かの引数(構造体)に入れられて戻ってくるとは思うのですが。もう少し調べてみたいと思います。

取り急ぎ、ありがとうございました。

お礼日時:2006/02/28 14:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A