2014-05-17 171 views
-1

我已經找到了網絡這個功能,工作得非常好德爾福多線程CMD

function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string; 
var 
    SA: TSecurityAttributes; 
    SI: TStartupInfo; 
    PI: TProcessInformation; 
    StdOutPipeRead, StdOutPipeWrite: THandle; 
    WasOK: Boolean; 
    Buffer: array[0..255] of AnsiChar; 
    BytesRead: Cardinal; 
    WorkDir: string; 
    Handle: Boolean; 
begin 
    Result := ''; 
    with SA do begin 
    nLength := SizeOf(SA); 
    bInheritHandle := True; 
    lpSecurityDescriptor := nil; 
    end; 
    CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0); 
    try 
    with SI do 
    begin 
     FillChar(SI, SizeOf(SI), 0); 
     cb := SizeOf(SI); 
     dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
     wShowWindow := SW_HIDE; 
     hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin 
     hStdOutput := StdOutPipeWrite; 
     hStdError := StdOutPipeWrite; 
    end; 
    WorkDir := Work; 
    Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine), 
          nil, nil, True, 0, nil, 
          PChar(WorkDir), SI, PI); 
    CloseHandle(StdOutPipeWrite); 
    if Handle then 
     try 
     repeat 
      WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); 
      if BytesRead > 0 then 
      begin 
      Buffer[BytesRead] := #0; 
      Result := Result + Buffer; 
      end; 
     until not WasOK or (BytesRead = 0); 
     WaitForSingleObject(PI.hProcess, INFINITE); 
     finally 
     CloseHandle(PI.hThread); 
     CloseHandle(PI.hProcess); 
     end; 
    finally 
    CloseHandle(StdOutPipeRead); 
    end; 
end; 

唯一的問題是,當我運行GetDosOutput它運行的第三方應用程序,這是非常沉重,我的應用程序時間太長,有時掛起 當我從線程調用這個函數它同樣需要很長時間來重播 任何建議,使此功能多線程?

+0

怎麼能多線程幫助? –

+0

我討厭這段代碼決定命名布爾成功值Handle。 –

+0

我不在乎,如果它只需要exe文件正常工作不會掛起 – dudey

回答

1

代碼的問題在於,WaitForSingleObject調用顯然是在主線程中執行的,因此阻塞了您的GUI(至少這是我從您的問題中瞭解到的)。

所以,你既可以:

  • 裹在TThread子類的.Execute的代碼。
  • 將呼叫替換爲MsgWaitForMultipleObjects,並在Windows消息到達時使用Application.ProcessMessages

你喜歡的東西:

repeat 
    case MsgWaitForMultipleObjects(1, PI.hProcess, False, INFINITE, QS_ALLINPUT) of 
    WAIT_OBJECT_0:  Break; 
    WAIT_OBJECT_0 + 1: Application.ProcessMessages(); 
    else Break; // should never happen 
    end; 
until False; 
+1

這種方法會導致重入問題。 – Torbins