DOSプログラムを実行させるには?


休息戦士  2005-09-21 17:37:37  No: 17637  IP: 192.*.*.*

お助けください。
環境は、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 で リアルタイム
    に表示させる方法がわかりません。

以上の問題を解消したいのですが、
誰か、お助けください。

編集 削除
Mr.XRAY  URL  2005-09-21 19:59:10  No: 17638  IP: 192.*.*.*

1.引数にSW_HIDEが使えませんでしたっけ.

2.Win32APIのGetLastErrorで取得できる?
    エラーコードもWin32APIの付録にあったと思います

3.リアルタイムというのがどういう状態を言うのかはわかりませんが,
    出力したファイルの内容を表示するというのはどうでしょう.

編集 削除
休息戦士  2005-09-21 21:28:25  No: 17639  IP: 192.*.*.*

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

編集 削除
Mr.XRAY  URL  2005-09-21 22:28:25  No: 17640  IP: 192.*.*.*

とりあえず1.だけ.

>wShowWindow := 0;  ← SW_HIDE のはず

私のDelphi5,6,7ではSW_HIDE=5となっています.

編集 削除
そんなはずは...  2005-09-21 22:51:40  No: 17641  IP: 192.*.*.*

>私のDelphi5,6,7ではSW_HIDE=5となっています.

Delphi6のwindows.pas には、
SW_HIDE = 0;
SW_SHOW = 5;
と定義されてますよ。

編集 削除
Mr.XRAY  URL  2005-09-21 23:55:00  No: 17642  IP: 192.*.*.*

>SW_SHOW = 5;
>と定義されてますよ。

あれまっ,スイマセン.違うコードでジャンプしてしまいました.
間違いです.やはり,休息戦士さんのコードで確認するしかないようですね.

編集 削除
休息戦士  2005-09-22 10:02:27  No: 17643  IP: 192.*.*.*

私も  1.だけ・・・

SI.wShowWindow := SW_HIDE;
だけでなく、
SI.dwFlags:= STARTF_USESHOWWINDOW;
を、設定すると表示しなくなりました。

祝!!  33%目的達成!!

編集 削除
半休  2005-09-22 10:07:11  No: 17644  IP: 192.*.*.*

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 にパイプ
  を作って接続。読み込みはパイプ経由。

編集 削除
半休  2005-09-22 12:32:53  No: 17645  IP: 192.*.*.*

3.以下が参考になると思います。
http://www.autch.net/tips/delphi_anonymous_pipe.php

これは子プロセス終了まで戻ってこないのですが、ループ中に表示処理(+Application.ProcessMessages)を入れる等をすればリアルタイム表示
出来ると思います。

関数中に表示処理その他をベタに書くと、(動くでしょうが)使い回しでき
ない関数に変わってしまうので、再利用性を保つなら、引数にイベントを
加えてループ中に呼ぶ等、なんらかの工夫が要ります。


また、子プロセス終了で読むのをやめているので、タイミングによっては
尻切れになる可能性があります。子プロセス終了後に再度パイプ中に残って
いるバッファを読んでやると安全です。

編集 削除
メラトニン  2005-09-22 17:15:04  No: 17646  IP: 192.*.*.*

コンソールアプリのエラー出力の点が不明ですが、
単にコンソール出力を得るだけなら戸田さんがすばらしいコンポーネントを公開しています。
http://www6.airnet.ne.jp/~sone_san/delphi/cgi-bin/ssi.cgi?miscella.html#MI0020

編集 削除