2

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 button.
Can you tell me whats wrong with my code?

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

The program stops responding when this code is executed.

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

There is also RedirectStandardError.
Hi @Dmitry Kurilo I have tried this method you have suggested. Thanks bro. But the thing is I want to put each line of output to a separate string. Later I'm gonna combine wanted lines and leave out the unwanted lines. and its not just for adb help. There are some other adb commands too that I wanna use. U get what I'm trying to do? Thanks Though.
Hi @Dmitry Kurilo. Thanks a lot bro. I fixed my problem. After taking a second look at your code I realized I had forgotten about this line. "pr.StandardInput.Close()" . I hadn't put it in my code. Works fine now. Thanks bro. God Bless You. Gonna give you the green tick after I apologize to Patsy for making him break his head on my code
1

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.

18 Comments

I'd drop the if (not process.HasExited) check as you could otherwise lose the last line(s) of output from the program.
@MarkHurd Thanks for the hint. I have removed the line.
@pasty I am not working only with the adb help command. I am also using some other commands of adb. I know the output can vary in length. I simply gave an array string of 20 assuming that the number of output lines is 20. But the thing is I want to get each output line and save it in a separate string. Then Later I want to utilize only the required outlines and not the unwanted ones by making use of only the required strings. How do I save each line of out put to a separate string?
I have updated my answer - now when the process is finished, only line 4 is outputed. You can change the code accordingly to your needs.
Hi @Pasty. I went through Dmitry Kurilo's answer again and I realised I hadn't put the line "pr.StandardInput.Close()". Now I've done that and its working fine. Sorry for making you go through all the trouble. I wanna give both of you the green tick mark but I don't know if that is possible. Thanks a lot man
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.