How to get Output of a Command Prompt Window line by line in Visual Basic?

前端 未结 2 1267
花落未央
花落未央 2020-12-20 00:07

I am trying to get a command line output line by line till the end of the output but I am not able to do so. I am using it in my Form and this code executes on click of a bu

相关标签:
2条回答
  • 2020-12-20 00:34

    I've done some research. adb help writes output into STDERR. So you need something like:

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

    to catch it.
    You need no 2>&1 if you call ipconfig, for example.

    0 讨论(0)
  • 2020-12-20 00:35

    Do not interate over the output and do not read it! Normally you don't know how long the output (same goes for error output too) would be, so you need to prepare for an unknown length. Since you are telling the Process class, that you want to handle the standard output and the standard error by yourself, you also need to bind to the events, in this case:

    • OutputDataReceived
    • ErrorDataReceived

    or to block the current process and read the complete output at once like @Dmitry Kurilo does in his answer. I find the first approach better because I do not need to wait for the process to end to see it's output. The MSDN documentation of the ProcessStartInfo.RedirectstandardError property gives a good explanation of the different possibilities with a lot of examples. If you want to take a specific line, there are a lot of possibilities. One would be to store each output (line) in the delegate and use it later, using a List(Of String) and output the specific line when the process is done (= all output lines are present).

    A possible solution could look like this:

    ' 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
    

    Now even if the adb writes to the error output, you will be able to see it. It will also be complete.

    The output in this case looks like this:

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

    Another possibility would be to put everything into one string and after the process has finished split the single string on line endings (CRLF \r\n) and you will gain the lines you want to filter.

    0 讨论(0)
提交回复
热议问题