cmd 的 Visual Basic 捕获输出 [英] Visual Basic Capture output of cmd

查看:14
本文介绍了cmd 的 Visual Basic 捕获输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望 Visual Basic 能够在目录C:projectTest"上运行make"命令.

I want Visual Basic to be able to run the "make" command on the directory "C:projectTest".

我尝试使用这个:

    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 会弹出).

This code is able to capture the "gcc ..." part of the console (comes from the Makefile), but will not capture the error (which does pop up if I manually open cmd and run make on that directory).

如何捕获出现的所有内容,包括错误?

How can I capture everything that appears including the error?

推荐答案

不止一个问题.首先,正如@shf301 已经告诉您的那样,您忘记阅读 stderr.他反过来忘记添加额外的一行:

More than one problem. First off, as @shf301 already told you, you forgot to read stderr. He in turn forgot to add an extra line:

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

还有另一个非常麻烦的问题,您的事件处理程序运行晚了.他们进程已经退出之后触发.这些处理程序在线程池线程上运行的副作用.在使用 output 变量之前,您需要等待一段任意(且不可猜测)的时间:

There's another very cumbersome problem, your event handlers run late. They fire after the process has already exited. A side effect of these handlers running on a thread-pool thread. You'll need to wait for an arbitrary (and unguessable) amount of time before you use the output variable:

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

这太丑了.以任何 IDE 或编辑器的方式执行此操作.将输出重定向到一个临时文件,然后读取该文件:

This is too ugly. Do this the way that any IDE or editor does it. Redirect the output to a temporary file and read the file afterwards:

    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

一些带有神秘命令行的注释:

Some annotation with the mystic command line:

  • /c 告诉 cmd.exe 只执行单个命令然后退出
  • 1> 将输出重定向到临时文件
  • 2>&1 告诉 cmd.exe 将 stderr 重定向到 stdout
  • 三重双引号确保临时文件名称中的空格不会造成麻烦.

同样的 2>&1 也可以解决你原来的问题;)

That same 2>&1 would also have fixed your original problem ;)

这篇关于cmd 的 Visual Basic 捕获输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆