簡體   English   中英

Visual Basic捕獲cmd的輸出

[英]Visual Basic Capture output of cmd

我希望Visual Basic能夠在目錄“C:\\ projectTest \\”上運行“make”命令。

我試着用這個:

    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,則會彈出錯誤)。

如何捕獲出現的所有內容,包括錯誤?

不止一個問題。 首先,正如@ 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

使用mystic命令行進行一些注釋:

  • / c告訴cmd.exe只執行單個命令然后退出
  • 1>將輸出重定向到臨時文件
  • 2>&1告訴cmd.exe將stderr重定向到stdout
  • 三重雙引號確保臨時文件名中的空格不會造成麻煩。

那個2>&1也會解決你原來的問題;)

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

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

像我這樣的人想知道為什么我們不能在異步模式下得到錯誤。 添加行

process.BeginErrorReadLine()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM