Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2005年02月15日] [更新 2013年10月21日] Delphi サンプルプログラム集
540_バッチファイルを CreateProcess 関数で実行
動作確認等 Windows 7 U64(SP1) + Delphi XE Pro
540_ConsoleBat2.zip [1,088 KB] 2013年10月21日版 (EXE 同梱)







バッチファイルを CreateProcess 関数で実行


拡張子が .BAT のファイルを,CreateProcess 関数を使用して実行するサンプルです.
CreateProcess 関数の他のサンプルと違うのは,実行ファイルがバッチファイルであることです.

本ページのサンプルは,コマンドプロセッサ (コマンドプロンプトを起動するプログラム) を非表示で起動して,バッチファイルに書かれたコマンドを実行します.
バッチファイルは実行時に作成しています.バッチファイルに書かれたコマンドの実行が終了したら,そのバッチファイル自身を自動的に削除します.
バッチファイルの内容は,

  • 指定したアプリケーションを起動
  • そのアプリケーションが終了するまで待ち,別のコマンドを実行
となっています.


[備考]
コマンドプロンプトに関しては以下の記事も参考にしてください.


図1
摂家時画面
  • ボタン 1 つだけのフォーム
図2
[バッチ処理] ボタンをクリック
  • ImageMetaFile.exe が起動する
  • コマンドプロンプトは非表示
  • 手前のフォームがバッチファイルで起動したプログラムのフォーム
  • このプログラムを終了するまで Form1 に戻らない
図3
終了
図4
バッチファイルの出力結果
  • フォルダ内に TestDir.txt ができる
図5
TestDir.txt の例

リスト1
CreateProcess 関数でバッチファイルを実行
バッチファイルをコード内で作成して,実行後,そのバッチファイルを削除
unit ConsoleBat2Unit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//-----------------------------------------------------------------------------
//  CreateProcess関数を使用して,指定したファイルを実行する
//  起動したアプリが終了するまでこの関数が終了しないコードになっている
//-----------------------------------------------------------------------------
function WinExecAndWait32V2(FileName: string; Visibility: Integer): DWORD;
var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
begin
  Result := 0;

  FillChar(StartupInfo, SizeOf(StartupInfo), #0);
  StartupInfo.cb          := SizeOf(TStartupInfo);
  StartupInfo.dwFlags     := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;

  SetLength(FileName, Length(FileName));

  //参照カウンタ対策
  UniqueString(FileName);
  if not CreateProcess(nil,
                       PChar(FileName),
                       nil,
                       nil,
                       False,
                       CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
                       nil,
                       nil,
                       StartupInfo,
                       ProcessInfo) then begin
    Result := WAIT_FAILED;
  end else begin
    //起動したプロセスが終了するまで待つ
    while WaitForSingleObject(ProcessInfo.hProcess, 100) = WAIT_TIMEOUT do
      Application.ProcessMessages;

    GetExitCodeProcess(ProcessInfo.hProcess, Result);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end;
end;

//=============================================================================
//  バッチファイルの実行例
//  (1)サンプルImageMetaFile.exeを実行し,終了まで待つ
//  (2)指定ディレクトリリストをこのフォルダにTestDir.txtで保存
//
//  BatFullPath バッチファイルの保存先
//  OutFullPath 出力先のファイルの保存先
//  TestExePath テスト用実行ファイル
//  終了後にDEL %0で作成したバッチファイル自身を削除する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  TestExePath : String;
  BatFullPath : String;
  OutFullPath : String;
  SL          : TStringList;
begin
  Self.Enabled := False;

  SL := TStringList.Create;
  try
    TestExePath := 'ImageMetaFile.exe';

    BatFullPath := ExtractFilePath(Application.ExeName) + 'Testbat.BAT';
    OutFullPath := ExtractFilePath(Application.ExeName) + 'TestDir.TXT';

    DeleteFile(OutFullPath);

    //バッチファイルを作成してこのアプリのフォルダに保存
    SL.Add(TestExePath);
    SL.Add('CD D:\');
    SL.Add('DIR>' + OutFullPath);
    SL.Add('DEL %0');
    SL.Add('EXIT');
    SL.SaveToFile(BatFullPath);
  finally
    FreeAndNil(SL);
  end;

  //バッチの実行
  WinExecAndWait32V2(BatFullPath, SW_HIDE);

  Self.Enabled := True;
  SetForegroundWindow(Handle);
  //CreateProcessの場合はここでも削除可能
  //DeleteFile(BatFullPath);
  Application.MessageBox('終了しました', 'バッチ処理', MB_OK);
end;

end.