2013-12-20 77 views
4

我希望Visual Basic能夠在目錄「C:\ projectTest \」上運行「make」命令。cmd的Visual Basic捕獲輸出

我試圖用這樣的:

Dim output As String = String.Empty 

    Using Process As New Process 
     Process.StartInfo = New ProcessStartInfo("cmd") 
     Process.StartInfo.WorkingDirectory = "C:\projectTest\" 
     Process.StartInfo.UseShellExecute = False 
     Process.StartInfo.CreateNoWindow = True 
     Process.StartInfo.RedirectStandardInput = True 
     Process.StartInfo.RedirectStandardOutput = True 
     Process.StartInfo.RedirectStandardError = True 
     Process.Start() 
     Process.BeginOutputReadLine() 
     AddHandler Process.OutputDataReceived, 
_ 
      Sub(processSender As Object, lineOut As DataReceivedEventArgs) 
       output += lineOut.Data + vbCrLf 
      End Sub 

     Using InputStream As System.IO.StreamWriter = Process.StandardInput 
      InputStream.AutoFlush = False 
      InputStream.WriteLine("make") 
     End Using 
     Do 
      Application.DoEvents() 
     Loop Until Process.HasExited 
    End Using 

此代碼是能捕捉到「GCC ......」控制檯(來自Makefile文件)的一部分,但不會捕獲錯誤(這不如果我手動打開cmd並在該目錄上運行make,就會彈出)。

如何捕獲包括錯誤在內的所有內容?

回答

7

不止一個問題。首先,正如@ shf301已經告訴你的那樣,你忘了閱讀stderr。他又忘了添加一行:

Process.Start() 
    AddHandler Process.OutputDataReceived, _ 
     Sub(processSender As Object, lineOut As DataReceivedEventArgs) 
      output += lineOut.Data + vbCrLf 
     End Sub 
    Process.BeginOutputReadLine() 
    AddHandler Process.ErrorDataReceived, _ 
     Sub(processSender As Object, lineOut As DataReceivedEventArgs) 
      output += lineOut.Data + vbCrLf 
     End Sub 
    Process.BeginErrorReadLine() 

還有另一個非常麻煩的問題,你的事件處理程序運行遲。他們在之後激活過程已經退出。這些處理程序在線程池線程上運行的副作用。你需要等待的任意時間(和難以猜測的)量使用輸出變量之前:

Do 
     Application.DoEvents() 
    Loop Until Process.HasExited 
    System.Threading.Thread.Sleep(1000) 

這是太醜陋了。按照的任何 IDE或編輯器的方式執行此操作。輸出重定向到一個臨時文件,然後需要讀取文件:

Dim tempfile As String = System.IO.Path.GetTempFileName 
    Using Process As New Process 
     Process.StartInfo = New ProcessStartInfo("cmd.exe") 
     Process.StartInfo.Arguments = "/c make 1> """ + tempfile + """ 2>&1" 
     Process.StartInfo.WorkingDirectory = "C:\projectTest" 
     Process.StartInfo.UseShellExecute = False 
     Process.StartInfo.CreateNoWindow = True 
     Process.Start() 
     Process.WaitForExit() 
     output = System.IO.File.ReadAllText(tempfile) 
     System.IO.File.Delete(tempfile) 
    End Using 

一些批註與神祕的命令行:

  • /C告訴cmd.exe執行只是單一的命令,然後退出
  • 1>將輸出重定向到臨時文件
  • 2> & 1告訴cmd.exe的重定向標準錯誤到stdout
  • 三重雙引號確保SPAC es在臨時文件名中不會造成麻煩。

就在同2>&1也修正了自己原來的問題;)

+0

你是高手!該代碼似乎也比以前更快地編譯該項目。 21小時過後,我會獎賞你的賞金:) – Jimmay

2

錯誤通常寫入StandardError流,您只能讀取StandardOutput流。爲ErrorDataReceived事件添加事件處理程序,您應該會看到這些錯誤。

AddHandler Process.ErrorDataReceived, _ 
     Sub(processSender As Object, lineOut As DataReceivedEventArgs) 
      output += lineOut.Data + vbCrLf 
     End Sub 
+0

謝謝,我補充說,但它仍然有完全相同的輸出(其缺少錯誤)。 – Jimmay

0

的人喜歡我,想知道爲什麼我們不能讓errorstream,在異步模式下。 附加線

process.BeginErrorReadLine()