2013-09-26 24 views
0

我用Delphi XE2編寫了需要執行命令行程序(也用Delphi XE2編寫)的VCL應用程序並獲取其輸出的文本。我目前使用下面的代碼,這是基於在這裏找到:Getting output from a shell/dos app into a Delphi app從Windows XP上的Delphi應用程序中的命令行程序獲取輸出

function GetDosOutput(ACommandLine : string; AWorkingDirectory : string): string; 
var 
    SecurityAttributes : TSecurityAttributes; 
    StartupInfo : TStartupInfo; 
    ProcessInformation: TProcessInformation; 
    StdOutPipeRead, StdOutPipeWrite: THandle; 
    WasOK: Boolean; 
    Buffer: array[0..255] of AnsiChar; 
    BytesRead: Cardinal; 
    Handle: Boolean; 
begin 
    Result := ''; 
    SecurityAttributes.nLength := SizeOf(TSecurityAttributes); 
    SecurityAttributes.bInheritHandle := True; 
    SecurityAttributes.lpSecurityDescriptor := nil; 
    CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SecurityAttributes, 0); 
    try 
    FillChar(StartupInfo, SizeOf(TStartupInfo), 0); 
    StartupInfo.cb := SizeOf(TStartupInfo); 
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
    StartupInfo.wShowWindow := SW_HIDE; 
    StartupInfo.hStdInput := StdOutPipeRead; 
    StartupInfo.hStdOutput := StdOutPipeWrite; 
    StartupInfo.hStdError := StdOutPipeWrite; 
    FillChar(ProcessInformation, SizeOf(ProcessInformation), 0); 
    Handle := CreateProcess(
     nil, 
     PChar(ACommandLine), 
     nil, 
     nil, 
     True, 
     0, 
     nil, 
     PChar(AWorkingDirectory), 
     StartupInfo, 
     ProcessInformation 
    ); 
    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(ProcessInformation.hProcess, INFINITE); 
     finally 
     CloseHandle(ProcessInformation.hThread); 
     CloseHandle(ProcessInformation.hProcess); 
     end; 
    finally 
    CloseHandle(StdOutPipeRead); 
    end; 
end; 

這適用於Windows的大多數版本的罰款。不幸的是,最近我們注意到它在Windows XP上不起作用。對WaitForSingleObject的調用根本不會返回。我嘗試用較小的值(例如15000)替換第二個參數INFINITE,但這似乎沒有任何區別。在任務管理器中,我可以看到,在調用GetDosOutput之後,命令行程序實際上正在運行。如果我結束了VCL應用程序,命令行程序然後似乎成功地完成了它的工作(證明它輸出我期待它的文件)。我也注意到,如果我從StartupInfo.dwFlags中刪除STARTF_USESTDHANDLES,命令行程序正常運行,WaitForSingleObject立即返回;但是我顯然無法獲得程序返回的文本。

有沒有人有關於如何在Windows XP上運行的建議?

+2

您可以找到正確的代碼在回答以下任務: http://stackoverflow.com/questions/9119999/getting-output-from-a-shell-dos-app-into-a-delphi-app/9120103#9120103 –

+5

我喜歡讀這一點:Handle:Boolean –

+1

@DavidHeffernan對於具有強類型背景的人來說,winAPI的BOOL類型可能會引起混淆。 – mg30rg

回答

1

有一個在FreePascal的所謂的「過程」一個真正有用的單元,它做到了這一點,並且,工作已經做了端口德爾福所以你可以在捕獲命令的輸出德爾福用一個簡單的襯墊:

RunCommand()

或者,你可以通過創建一個對象T加工自己(這RunCommand只是包裝)捕捉更先進的功能的命令的輸出。

該項目是在這裏:

如何捕獲一個命令的輸出,即 「dir」(在列表目錄內容,著名的MS DOS命令)轉換爲字符串,然後將其添加到備忘錄中:

uses 
    dprocess; 
// ... 
var 
    output: ansistring; 
begin 
    RunCommand('cmd', ['/c', 'dir'], output, [poNoConsole]); 
    memo1.Lines.Add(output); 
end; 
+0

你打算髮布相同的答案提及ShellExecute的每個問題? –

相關問題