ShellExecuteで終了を待つ方法は?


イチロ  2004-12-03 21:57:07  No: 12069

ShellExecuteで起動した子プロセスの終了を知る方法はありますでしょうか?
以前から、CreateProcessで起動させるルーチンは紹介されていますが、
事情により(ショートカットを起動させるため)、CreateProcessは使えず
ShellExecuteで起動させています。

子プロセスの起動中は、親フォームを表示せず、
子プロセスの終了を検知して親フォームを可視状態にしようと思っています。(どちらか片方しか表示されない状態)

以下のソースでは子プロセスの起動はできますが、
終了をうまく検知しないためか、両方のフォームが表示されてしまいます。
無理やりShellExecuteの戻り値を取得しようと思ったのがいけないのでしょうか?

どなたか知恵を貸してください。

procedure TMastMenu.SpeedButton1Click(Sender: TObject);
var
   s        : string;
   ProgName : PChar;
   handle   : THandle;
   tpi       : TProcessInformation;
begin
   s := 'C:\abcへのショートカット.lnk';
   ProgName := PChar(sWorks);

   //ショートカットプログラムを起動
   Handle := ShellExecute(Application.MainForm.Handle, nil,ProgName, nil, nil,SW_SHOW);
   tpi.hProcess := handle;

   //プロセスが終了するのを待つ
   while WaitForSingleObject(tpi.hProcess, INFINITE) = WAIT_TIMEOUT do
   begin
      Application.ProcessMessages;
      Self.Visible := false;
   end; 

   Self.Visible := true;
end;


さわ  2004-12-04 02:48:34  No: 12070

GetExitCodeProcessでStillActiveの間待たせるとか?


りおりお  2004-12-04 03:06:02  No: 12071

いや、ShellExecute では、そもそもプロセスハンドルが取得できません。

素直に、ショートカットなときは、実行ファイルを取得して CreateProcess を
使ってください。


Fusa  2004-12-04 06:21:23  No: 12072

りおりおさんのいうように

こんなので
ショートカットファイルの実行ファイルを取得して
CreateProcessを呼びましょう。

type
  TShowCommand = (scNormalWindow, scMinimize, scMaxmize, scUnknown);

  TShortcurFile = class(TObject)
  private
    ShellLink:IShellLink;
    PersistFile:IPersistFile;
    FilePath:array[0..MAX_PATH] of char;
    WorkDir:array[0..MAX_PATH] of char ;
    wsz:Array[0..MAX_PATH] of WideChar;
    pwHotKey:Word;
    pShowCmd:integer;
    pfd:TWin32FindData;

    FSourceFileName: TFileName;
    FFileName: TFileName;
    FShowCommand: TShowCommand;
    FHotKey: Word;
  protected
  public
    constructor Create(FileLink: TFileName);
    destructor Destroy; override;
  published
    property FileName: TFileName read FFileName;
    property SourceFileName: TFileName read FSourceFileName;
    property HotKey: Word read FHotKey;
    property ShowCommand: TShowCommand read FShowCommand;
  end;

{ TShortcurFile }

constructor TShortcurFile.Create(FileLink: TFileName);
begin
  if not FileExists(ChangeFileExt(FileLink,'.lnk')) then
    raise Exception.Create('ファイルが存在しません');

  inherited Create;

  ShellLink := CreateComObject(CLSID_ShellLink) As IShellLink;
  try
      OleCheck(ShellLink.QueryInterface(IPersistFile,PersistFile));
      Assert(Assigned(PersistFile));
      MultiByteToWideChar(CP_ACP,0,PChar(FileLink),-1,wsz,MAX_PATH);
      OleCheck(PersistFile.Load(wsz,0));

      OleCheck(ShellLink.GetPath(FilePath,MAX_PATH,pfd,SLGP_SHORTPATH));
      FFileName := FilePath;

      OleCheck(ShellLink.GetWorkingDirectory(WorkDir,MAX_PATH));
      FSourceFileName := WorkDir;

      OleCheck(ShellLink.GetHotKey(pwHotkey));
      FHotKey := pwHotKey;

      OleCheck(ShellLink.GetShowCmd(pShowCmd));
      case pShowCmd of
        1: FShowCommand := scNormalWindow;
        7: FShowCommand := scMinimize;
        3: FShowCommand := scMaxmize;
      else
        FShowCommand := scUnknown;
      end;

  except on EOleSysError do
    raise Exception.Create('OLEエラーが発生しました');
  end;
end;


n  2004-12-16 13:53:35  No: 12073

ShellExecuteでの終了待ちは出来ません。
ShellExecuteExとWaitForSingleObjectを使いましょう。


ぷりお  2005-01-06 02:50:48  No: 12074

以下はボタン(Button1)をクリックするとメモ帳が起動され、ユーザーがそのメモ帳を終了するまで待機する例です。
参考になるでしょうか?

procedure TForm1.Button1Click( Sender: TObject);
var
  SXInfo: TShellExecuteInfo;
begin
  with SXInfo do//TShellExecuteInfo構造体の初期化
  begin
    cbSize := SizeOf( SXInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS;//これがないと終了待ち出来ない
    Wnd := Application.Handle;
    lpVerb := 'open';
    lpFile := PChar( 'notepad.exe');
    lpParameters := Nil;
    lpDirectory := Nil;
    nShow := SW_SHOW;
  end;

  ShellExecuteEx( @SXInfo);
  Button1.Enabled := False;//メモ帳がいくつも起動されるとまずいので...

  //起動したアプリケーションの終了待ち
  while WaitForSingleObject( SXInfo.hProcess, 0) = WAIT_TIMEOUT do
    Application.ProcessMessages;

  ShowMessage( '終わったよ!');
  Button1.Enabled := True;
end;

元はhttp://www.asahi-net.or.jp/~GV4J-SGUR/narik/stp001.htm#SHGetSpecialFolderLocationです


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加