如何在Visual Basic中逐行输出命令提示符窗口?

时间:2014-10-13 19:50:38

标签: vb.net cmd

我试图逐行获取命令行输出,直到输出结束,但我无法这样做。我在我的表单中使用它,此代码在单击按钮时执行。
你能告诉我我的代码有什么问题吗?

Dim proc As ProcessStartInfo = New ProcessStartInfo("cmd.exe")
    Dim pr As Process
    proc.CreateNoWindow = True
    proc.UseShellExecute = False
    proc.RedirectStandardInput = True
    proc.RedirectStandardOutput = True
    pr = Process.Start(proc)
    pr.StandardInput.WriteLine("cd C:\sdk\platform-tools\")
    pr.StandardInput.WriteLine("adb help")
    Dim helpArray(20) as String
    For i as Integer 1 To 7
    helpArray(i) = pr.StandardOutput.ReadLine()
    Next
    pr.StandardOutput.Close()

执行此代码时程序停止响应。

2 个答案:

答案 0 :(得分:2)

我做过一些研究。 adb help将输出写入STDERR。所以你需要这样的东西:

    Dim proc As ProcessStartInfo = New ProcessStartInfo("cmd.exe")
    Dim pr As Process
    proc.CreateNoWindow = True
    proc.UseShellExecute = False
    proc.RedirectStandardInput = True
    proc.RedirectStandardOutput = True
    pr = Process.Start(proc)
    pr.StandardInput.WriteLine("C:\sdk\platform-tools")
    pr.StandardInput.WriteLine("adb help 2>&1")
    pr.StandardInput.Close()
    Console.WriteLine(pr.StandardOutput.ReadToEnd())
    pr.StandardOutput.Close()

抓住它。
例如,如果你调用ipconfig,则不需要2>& 1。

答案 1 :(得分:1)

不要对输出进行交互而不要阅读它!通常你不知道输出多长时间(同样也是错误输出),所以你需要准备一个未知的长度。既然您要告诉Process类,您想要自己处理标准输出标准错误,那么您还需要bind to the events,在这种情况下:

  • OutputDataReceived
  • ErrorDataReceived

或阻止当前进程并立即阅读完整输出,就像@Dmitry Kurilo在答案中所做的那样。我发现第一种方法更好,因为我不需要等待进程结束才能看到它的输出。 ProcessStartInfo.RedirectstandardError property的MSDN文档通过大量示例很好地解释了不同的可能性。 如果你想采取特定的路线,有很多可能性。一种方法是将每个输出(行)存储在委托中,稍后使用List(Of String)使用它,并在完成该过程时输出特定行(=所有输出行都存在)。

可能的解决方案可能如下所示:

' store error output lines
dim lines = new List(of String)

dim executable = "c:\temp\android\sdk\platform-tools\adb.exe"
dim arguments = " help"
dim process = new Process()
process.StartInfo = createStartInfo(executable, arguments)
process.EnableRaisingEvents = true
addhandler process.Exited, Sub (ByVal sender As Object, ByVal e As System.EventArgs) 
    Console.WriteLine(process.ExitTime)
    Console.WriteLine(". Processing done.")
    ' output line n when output is ready (= all lines are present)
    Console.WriteLine(lines(4))
end sub
' catch standard output
addhandler process.OutputDataReceived, Sub (ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) 
        if (not String.IsNullOrEmpty(e.Data))
            Console.WriteLine(String.Format("{0}> {1}", DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") ,e.Data))
        end if
end sub
' catch errors
addhandler process.ErrorDataReceived, Sub (ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) 
    'Console.WriteLine(String.Format("! {0}", e.Data))
    ' add every output line to the list of strings
    lines.Add(e.Data)
end sub
' start process
dim result = process.Start()
' and wait for output
process.BeginOutputReadLine()
' and wait for errors :-)
process.BeginErrorReadLine()

private function createStartInfo(byval executable as String, byval arguments as String) as ProcessStartInfo
    dim processStartInfo = new ProcessStartInfo(executable, arguments)
    processStartInfo.WorkingDirectory = Path.GetDirectoryName(executable)
    ' we want to read standard output
    processStartInfo.RedirectStandardOutput = true
    ' we want to read the standard error
    processStartInfo.RedirectStandardError = true
    processStartInfo.UseShellExecute = false
    processStartInfo.ErrorDialog = false
    processStartInfo.CreateNoWindow = true
    return processStartInfo
end function

现在即使 adb 写入错误输出,您也可以看到它。它也将完整。

这种情况下的输出如下所示:

14.10.2014 12:49:10
. Processing done.
 -e                            - directs command to the only running emulator.

另一种可能性是将所有内容放入一个字符串中,并且在该过程完成后将单个字符串拆分为行结尾(CRLF \ r \ n),您将获得要过滤的行。