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

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

问题描述

我要的Visual Basic,以便能够运行在目录中的make命令C:\ projectTest \。

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

这code能够捕捉到了海湾合作委员会......控制台(来自Makefile文件)的一部分,但不会捕获错误(如果我手动打开CMD这不弹出并运行作出该目录)。

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已经告诉你了,你忘了阅读标准错误。他又忘了添加一个额外的行:

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

还有一个非常麻烦的问题,你的事件处理程序的后期运行。他们火的 的过程中已经退出之后。这些处理程序在一个线程池线程运行的一个副作用。你们需要使用之前要等待的时间任意(和难以猜测的)量的输出的变量:

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天全站免登陆