2017年9月7日 星期四

等待外部執行檔結束作業後, 再繼續執行後續的程式碼

uses ShellAPI;

procedure TForm1.pr_WaitForProcess(sFile, sParameter:String);
var
    ExitCode: cardinal;
    ExecInfo: TShellExecuteInfo;
begin
  ZeroMemory(@ExecInfo,SizeOf(ExecInfo));
  with ExecInfo do
  begin
    cbSize := SizeOf(ExecInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS;
    lpVerb := 'open';
    lpFile := PChar(sFile); //執行檔檔名
    lpParameters := PChar(sParameter); //參數
    Wnd := 0;
    nShow := SW_SHOWNORMAL;
  end;
  ShellExecuteEx(@ExecInfo);
  GetExitCodeProcess(ExecInfo.hProcess,ExitCode);
  while ExitCode=STILL_ACTIVE do
  begin
    GetExitCodeProcess(ExecInfo.hProcess, ExitCode);
    sleep(10);
    Application.ProcessMessages;
  end;
end;




fatmoon1 對直接取用ShellExecute回傳值使用於WaiteforSingleObject的見解

引言:
引言:

procedure TForm1.Button1Click(Sender: TObject);
var
    aHandle: Hwnd;
begin
    //WinExec('D:\WinRAR\Rar.exe a -r E:\ShareFile.rar E:\ShareFile', SW_SHOWNORMAL);
    aHandle := ShellExecute(Self.Handle, 'Open', 'rar.exe', ' a -r E:\ShareFile.rar E:\ShareFile', 'D:\WinRAR\', SW_SHOWNORMAL);
    WaitForSingleObject(aHandle, INFINITE);
    ShowMessage('成功!')
end;


雖然已經有正確解答了,但我針對上述方法會失敗的原因來回應
上述方法會失敗的原因是因為
aHandle:=ShellExecute(Self.Handle, 'Open', 'rar.exe', ' a -r E:\ShareFile.rar E:\ShareFile', 'D:\WinRAR\', SW_SHOWNORMAL);
如此的話aHandle只是存入ShellExecute的回傳值(成功的話回傳值會大於32)
所以WaitForSingleObject(aHandle, INFINITE);此行根本沒等到正確的Handle值

而WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD);
這個函式的作用是 等候 hHandle(執行程式的Handle值) dwMilliseconds(ms)
所以經過dwMilliseconds(ms)後仍會執行下一行
所以要改寫成

var Result: Boolean;
    ShellExInfo: TShellExecuteInfo;
begin
    FillChar(ShellExInfo, SizeOf(ShellExInfo), 0);
    with ShellExInfo do begin
    cbSize := SizeOf(ShellExInfo);
    fMask := see_Mask_NoCloseProcess;
    Wnd := Application.Handle;
    lpFile := 'D:\WinRAR\Rar.exe';
    lpDirectory := 'D:\WinRAR\';
    lpParameters := ' a -r E:\ShareFile.rar E:\ShareFile';
    nShow := SW_SHOWNORMAL;
    end;
//上述程式碼與william兄是一樣的,不一樣的在下方
    Result := ShellExecuteEx(@ShellExInfo);
    if Result then
    while WaitForSingleObject(ShellExInfo.HProcess, 100) = WAIT_TIMEOUT do
    begin
        Application.ProcessMessages;
        if Application.Terminated then Break;
    end;
end;


=========================
fat eat moon,fat eat moon

轉貼至 http://delphi.ktop.com.tw/board.php?cid=30&fid=72&tid=38858

沒有留言:

張貼留言