Vb.net 如何在Visual Basic中逐行获取命令提示窗口的输出?

Vb.net 如何在Visual Basic中逐行获取命令提示窗口的输出?,vb.net,cmd,Vb.net,Cmd,我试图逐行获取命令行输出,直到输出结束,但我无法这样做。我在表单中使用它,这个代码在单击按钮时执行 你能告诉我我的密码有什么问题吗 Dim proc As ProcessStartInfo = New ProcessStartInfo("cmd.exe") Dim pr As Process proc.CreateNoWindow = True proc.UseShellExecute = False proc.RedirectStandardInput = Tr

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

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()

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

我做了一些研究。adb帮助将输出写入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。

不要对输出进行交互,也不要读取它!通常情况下,您不知道输出的长度(错误输出也是如此),因此需要为未知长度做好准备。由于您告诉Process类,您希望自己处理标准输出和标准错误,因此在这种情况下,您还需要:

  • 输出数据接收
  • 收到错误数据
或者像@Dmitry Kurilo在回答中所做的那样,阻止当前进程并立即读取完整的输出。我发现第一种方法更好,因为我不需要等待进程结束才能看到它的输出。的MSDN文档通过大量示例很好地解释了不同的可能性。 如果你想走一条特定的路线,有很多可能性。一种方法是将每个输出(行)存储在委托中,稍后使用它,使用
列表(字符串)
,并在流程完成时输出特定行(=所有输出行都存在)

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

' 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
14.10.2014 12:49:10
. Processing done.
 -e                            - directs command to the only running emulator.
现在,即使adb写入错误输出,您也可以看到它。它也将完成

本例中的输出如下所示:

' 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
14.10.2014 12:49:10
. Processing done.
 -e                            - directs command to the only running emulator.

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

还有
重定向标准错误
。Hi@Dmitry Kurilo我尝试了您建议的此方法。谢谢兄弟。但问题是我想把每一行输出放到一个单独的字符串中。稍后,我将合并需要的行,并删除不需要的行。这不仅仅是为了亚洲开发银行的帮助。我还想使用其他一些adb命令。你明白我想做什么吗?谢谢。嗨,德米特里·库里洛。非常感谢兄弟。我解决了我的问题。再看一遍你的代码后,我意识到我忘记了这一行。“pr.StandardInput.Close()”。我没有把它写进我的密码里。现在一切正常。谢谢兄弟。上帝保佑你。在我向Patsy道歉让他在我的代码上撞了头之后,我会给你绿色的记号。如果(不是进程。已退出)检查,否则你可能会丢失程序输出的最后一行。@MarkHurd谢谢你的提示。我已删除该行。@pasty我不仅仅使用adb help命令。我还使用了adb的一些其他命令。我知道输出的长度可能不同。我只给出了一个数组字符串20,假设输出行的数量是20。但问题是我想得到每个输出行并将其保存在单独的字符串中。然后,稍后我想只利用所需的轮廓,而不是不需要的轮廓,只利用所需的字符串。如何将out的每一行保存到一个单独的字符串中?我已经更新了我的答案-现在当流程完成时,只输出第4行。您可以根据需要更改代码。嗨@Pasty。我又看了一遍Dmitry Kurilo的答案,我意识到我没有把“pr.StandardInput.Close()”这一行放进去。现在我已经做到了,而且效果很好。很抱歉让你经历了所有的麻烦。我想给你们两个打绿色记号,但我不知道这是否可行。谢谢你,伙计