Standard urge.

I run the process in my C # application, which launches the console application. I redirected standard input and output and was able to read multiple lines through StandardOutput.ReadLine (). I am sure that ProcessStartInfo is configured correctly.

The console application at startup displays several lines (ends with a marker line), and then waits for input. After receiving the input, it again displays several lines (again ends with the line "marker"), etc. My intention is to read the lines from it until I get the string "marker", after which I know to send the corresponding input line.

My problem is that after several iterations the program freezes. Suspending a debugger tends to place a hang in a call to StandardOutput.EndOfStream. This takes place in the following test code:

while (!mProcess.StandardOutput.EndOfStream) // Program hangs here. { Console.WriteLine(mProcess.StandardOutput.ReadLine()); } 

When I test the marker line, I get the same kind of hang if I try to access the StandardOutput.EndOfStream standard after reading the line:

 string line = ""; while (!isMarker(line)) { line = mProcess.StandardOutput.ReadLine(); } bool eos = mProcess.StandardOutput.EndOfStream; // Program hangs here. 

What can I do, does this make this property work so horribly?

+4
source share
4 answers

You cannot reliably use EndOfStream here. The StreamReader.EndOfStream property will call StandardOutput.Read () if it does not have buffered characters. This call to Read () blocks if the process does not send anything to its output channel and does not close it. Which is pretty much guaranteed, as it will wait for input. EndOfStream will not return true until the process completes the end of the output channel, and StreamReader uses all of its buffered characters. At the end of the program.

Using BeginOutputReadLine () may be the best way to define a marker string. Remember that the callback happens on a different thread. Also note that there is no need to wait until the process sends a marker, everything you write will be buffered until the process is ready to read it. Remember that buffers are small; deadlock is possible.

+9
source

There are many ways for which you can create a dead end when interacting with a process class. Microsoft describes them on the MSDN website here . This is what I call it. Note the handling of ErrorDataReceived and OutputDataReceived and the calls to BeginErrorReadLine and BeginOutputReadLine. This eliminates deadlock scenarios because the parent process processes threads asynchronously. NOTE. RunProcessResponse is my own wrapper data transfer object.

 Public Function RunProcess(ByVal executableFileName As String, ByVal arguments As String, ByVal workingDirectory As System.String) As RunProcessResponse Dim process As System.Diagnostics.Process = Nothing Dim response As RunProcessResponse Try process = New System.Diagnostics.Process() Dim psInfo As New System.Diagnostics.ProcessStartInfo() Dim errorString As System.String = String.Empty Dim outputString As System.String = String.Empty If Not System.String.IsNullOrEmpty(workingDirectory) Then psInfo.WorkingDirectory = workingDirectory End If psInfo.FileName = executableFileName psInfo.Arguments = arguments psInfo.WindowStyle = ProcessWindowStyle.Hidden psInfo.CreateNoWindow = True psInfo.RedirectStandardError = True psInfo.RedirectStandardOutput = True psInfo.UseShellExecute = False AddHandler process.ErrorDataReceived, Sub(sender As Object, args As DataReceivedEventArgs) If args.Data IsNot Nothing Then errorString &= args.Data & vbCrLf End If End Sub AddHandler process.OutputDataReceived, Sub(sender As Object, args As DataReceivedEventArgs) If args.Data IsNot Nothing Then outputString &= args.Data & vbCrLf End If End Sub process.StartInfo = psInfo process.Start() process.BeginErrorReadLine() process.BeginOutputReadLine() process.WaitForExit() response = New RunProcessResponse(errorString, outputString, process.ExitCode) Return response Finally If process IsNot Nothing Then process.Dispose() End If End Try End Function 
+1
source

You waited for the process to complete before reading the standard output from it:

 mProcess.WaitForExit(); 
0
source

If you know that after it there is no longer standard input:

 while (!mProcess.StandardOutput.EndOfStream) 

you can close the standard input with:

 mProcess.StandardInput.Close(); 

To signal that there is no more input. As long as the standard input is open, there is the potential for more input, thus more output; therefore, standard output will never reach EndOfStream.

0
source

Source: https://habr.com/ru/post/1308800/


All Articles