2014-07-01 25 views
2

我有Delphi代碼,用於從給定的參數集合中運行JAVA_HOME的Java.exe。這是通過將Create命令傳遞給CreateProcess()來實現的。對於一組特定的輸入參數,這給了我一個錯誤,說「無法創建Java虛擬機」。我需要通過PeekNamedPipe()將其轉換爲Delphi代碼並將其顯示在應用程序中。我怎樣才能做到這一點? 德爾福代碼如下所示:如何使用PeekNamedPipe()從Delphi代碼讀取運行控制檯應用程序的錯誤

begin 
    securityAttr.nlength := SizeOf(TSecurityAttributes); 
    securityAttr.binherithandle := true; 
    securityAttr.lpsecuritydescriptor := nil; 

    if CreatePipe (readPipe, writePipe, @securityAttr, 0) then 
    begin 

    buffer := AllocMem(READ_BUFFER + 1); 
    FillChar(startInfo, Sizeof(startInfo), #0); 
    startInfo.cb   := SizeOf(startInfo); 
    startInfo.hStdOutput := writePipe; 
    startInfo.hStdInput := readPipe; 
    startInfo.dwFlags  := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; 
    startInfo.wShowWindow := SW_HIDE; 

    if SearchPath(nil, PChar(consoleApp), '.exe', SizeOf(consoleAppBuf), consoleAppBuf, exeName) = 0 then 
    raise EInOutError.CreateFmt('Could not find file %s', [consoleApp]); 

FmtStr(commandLine, '"%s" %s', [consoleAppBuf, parameters]); 

if CreateProcess(nil, PChar(commandLine), nil, nil, true, CREATE_NO_WINDOW, nil, nil, startInfo, processInfo) then 
begin 

    totalBytesRead := 0; 

    repeat   
    exitCode := WaitForSingleObject(ProcessInfo.hProcess, 100); 
    Application.ProcessMessages; 

    if (PeekNamedPipe(readPipe, @buffer[totalBytesRead], 
         READ_BUFFER, @bytesRead, 
         @totalBytesAvail, @bytesLeftThisMessage)) then 
    begin 

     if (bytesRead > 0) then 
     ReadFile(readPipe, buffer[totalBytesRead], bytesRead, bytesRead, nil); 

     totalBytesRead := totalBytesRead + bytesRead; 

    end; 

    until (exitCode <> WAIT_TIMEOUT); 

    GetExitCodeProcess(ProcessInfo.hProcess, result); 

    buffer[totalBytesRead]:= #0; 
    OemToChar(buffer, buffer); 
    output.Text := output.Text + StrPas(buffer); 

    FreeMem(buffer); 
    CloseHandle(processInfo.hProcess); 
    CloseHandle(processInfo.hThread); 
    CloseHandle(readPipe); 
    CloseHandle(writePipe); 

end 
else 
    RaiseLastWin32Error; 

end; 

我如何可以讀取的java.exe拋出的錯誤?

+0

爲什麼您使用同一個管道將流程的標準輸入/輸出連接起來?你在做什麼試圖達到什麼目的?或者你只是隨意嘗試管道?這個代碼是否可以做任何事情?流程的輸出在哪裏去? stdout或stderr? –

+0

這是從delphi函數運行控制檯應用程序的片段。它將爲命令行參數創建Process()並讀取進程的結果。該進程的輸出進入PeekNamedPipe的輸入緩衝區。然而,只有當java.exe運行成功而沒有任何錯誤時纔會發生。我需要捕獲運行java.exe時出現的錯誤 – jetty

+0

請再次發表我的評論。爲什麼將同一個管道的兩端連接到相同的流程標準句柄? –

回答

1

將相同管道的兩端連接到同一進程的輸入和輸出是錯誤的。您正在將該過程的輸出反饋回其輸入。請將hStdInput作爲NULL

您還可以快速鬆動地進行錯誤檢查,並且由於不使用finally塊而可能會出現手柄泄漏的風險。而我並不熱衷於繁忙的循環。或致電ProcessMessages

讓所有人置身事外,你沒有閱讀錯誤的可能原因是他們會走向stderr。將管道的寫入端連接到stderr以及stdout:

startInfo.hStdOutput := writePipe; 
startInfo.hStdError := writePipe; 
+1

我讀了一些關於使用NamedPipe和process的概念。意識到將管道的兩端連接到進程的i/p和o/p是一個錯誤。糾正了這一點。另外,將hStdError添加到我的startInfo並且它工作正常!謝謝 – jetty

相關問題