お助けください。
環境は、Delphi7、WindowsXPです。
DelphiからDOSで動作するプログラムを呼び出します。
実行はできました。
終了をまってから次の実行をおこないたいので、
CreateProcess を使用しています。
問題点が3つあります。
1.CreateProcess でよびだして実行はできるのですが
Dos窓が表示されてします。このDos窓が表示しないように
するにはどうすればよいのでしょうか?
2.CreateProcess でよびだした実行ファイル(プログラム)が
エラーを発生した場合のエラー番号はどうやって取得するのでしょうか?
CreateProcessのリターン値だと0が失敗で、0以外は成功になります。
バッチファイルだと以下のようになります。この ERRORLEVEL を
取得したいのです。
Get > report.lst
if ERRORLEVEL 1 goto END
3.2.のバッチファイルで、「 > report.lst 」の部分ですが、
この 出力ファイルの変わりに Memo や、RichEdit で リアルタイム
に表示させる方法がわかりません。
以上の問題を解消したいのですが、
誰か、お助けください。
1.引数にSW_HIDEが使えませんでしたっけ.
2.Win32APIのGetLastErrorで取得できる?
エラーコードもWin32APIの付録にあったと思います
3.リアルタイムというのがどういう状態を言うのかはわかりませんが,
出力したファイルの内容を表示するというのはどうでしょう.
>1.引数にSW_HIDEが使えませんでしたっけ.
wShowWindow := 0; ← SW_HIDE のはず
引数が間違っているのでしょうか?
>2.Win32APIのGetLastErrorで取得できる?
> エラーコードもWin32APIの付録にあったと思います
GetLastError でリターン値を取得しました。
わざとエラーが出るようにして呼び出しても0しか返ってきません
>3.リアルタイムというのがどういう状態を言うのかはわかりませんが,
> 出力したファイルの内容を表示するというのはどうでしょう.
ファイル出力の場合だと、呼び出したプログラムが終了してからでないと
結果が表示できないので、stdout で出力されているだろうから
その結果を処理と平行しながら表示したいのです。
☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
以下現状のソースです
☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
☆呼び出し側
ProcessDir := 'D:\Source';
ProcessFile := ProcessDir + '\Source.bpr';
if FileExists(ProcessFile) then begin
if SetCurrentDir(ProcessDir) then begin
ProgramMakeExecute('-fSource.mak > make.lst');
end;
end;
☆呼び出されている関数
function TForm1.ProgramMakeExecute(CmdStr: String): Integer;
var
SI: TStartupInfo;
PI: TProcessInformation;
CurrentDir: String;
FileName: String;
CommandStr: String;
begin
CurrentDir := GetCurrentDir;
FileName := 'C:\Program Files\Borland\Delphi7\Bin\make.exe';
CommandStr := FileName + ' ' + CmdStr;
with SI do begin
Cb := SizeOf(SI);
lpReserved := Nil;
lpDesktop := Nil;
lpTitle := Nil;
dwX := 0;
dwY := 0;
dwXSize := 0;
dwYSize := 0;
dwXCountChars := 0;
dwYCountChars := 0;
dwFillAttribute := 0;
dwFlags := 0;
wShowWindow := 0;
cbReserved2 := 0;
lpReserved2 := Nil;
hStdInput := 0;
hStdOutput := 0;
hStdError := 0;
end;
if CreateProcess(PChar(FileName), PChar(CommandStr), Nil, Nil, False, 0, Nil, PChar(CurrentDir), SI, PI) then begin
// 処理終了を待つ
while WaitForSingleObject(PI.hProcess, 0) = WAIT_TIMEOUT do Application.ProcessMessages;
end;
Result := GetLastError;
end;
とりあえず1.だけ.
>wShowWindow := 0; ← SW_HIDE のはず
私のDelphi5,6,7ではSW_HIDE=5となっています.
>私のDelphi5,6,7ではSW_HIDE=5となっています.
Delphi6のwindows.pas には、
SW_HIDE = 0;
SW_SHOW = 5;
と定義されてますよ。
>SW_SHOW = 5;
>と定義されてますよ。
あれまっ,スイマセン.違うコードでジャンプしてしまいました.
間違いです.やはり,休息戦士さんのコードで確認するしかないようですね.
私も 1.だけ・・・
SI.wShowWindow := SW_HIDE;
だけでなく、
SI.dwFlags:= STARTF_USESHOWWINDOW;
を、設定すると表示しなくなりました。
祝!! 33%目的達成!!
1.wShowWindow の他に dwFlags に STARTF_USESHOWWINDOW の設定も必要
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.wShowWindow := SW_HIDE;
2.GetExitCodeProcess(PI.hProcess, ...) で出来ると思う。
3.SI.dwFlags に STARTF_USESTDHANDLES つけて SI.hStdOutput にパイプ
を作って接続。読み込みはパイプ経由。
3.以下が参考になると思います。
http://www.autch.net/tips/delphi_anonymous_pipe.php
これは子プロセス終了まで戻ってこないのですが、ループ中に表示処理(+Application.ProcessMessages)を入れる等をすればリアルタイム表示
出来ると思います。
関数中に表示処理その他をベタに書くと、(動くでしょうが)使い回しでき
ない関数に変わってしまうので、再利用性を保つなら、引数にイベントを
加えてループ中に呼ぶ等、なんらかの工夫が要ります。
また、子プロセス終了で読むのをやめているので、タイミングによっては
尻切れになる可能性があります。子プロセス終了後に再度パイプ中に残って
いるバッファを読んでやると安全です。
コンソールアプリのエラー出力の点が不明ですが、
単にコンソール出力を得るだけなら戸田さんがすばらしいコンポーネントを公開しています。
http://www6.airnet.ne.jp/~sone_san/delphi/cgi-bin/ssi.cgi?miscella.html#MI0020
ツイート | ![]() |