Process.StandardOutput stops reading - c#

I am trying to run a process, hide its window and then print its output in my program. I am achieving it with this code:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = path,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
Verb = "runas"
}
};
proc.Start();
while(!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
Console.WriteLine(line);
}
It works with other programs but for this one it's stopping at some point. My guess is that it sends too much messages, because before actually loading it spams a ton of messages that say: "Initializing... n%". It reads it until it reaches around 90-95% and then stops reading. My guess is that it can't read anymore because it sent too much messages. What can I do to read the whole output?

I found out how to make a workaround. It turns out the program actually needed input inbetween the initialization and the actual result. Thanks to #Alexandru Clonțea I decided that I would not run the process, but create a .bat file, which contains the following command:
program.exe > output.txt < input.txt
Where program.exe is the executable, output.txt is the file that is going to contain the output of the program and input.txt in my case is just an empty text file so I can just get some kind of an input and make the program finish.

Related

Execute a batch file from c# and store result into a variable

I am writing a program that is running a batch file, and will need the output further in the program. this is my C# code:
public void ExecuteBatFile()
{
Process proc = null;
try
{
string targetDir = string.Format("C:\\Users"); //this is where mybatch.bat lies
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = "batch.bat";
proc.StartInfo.Arguments = string.Format("10"); //this is argument
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //this is for hiding the cmd window...so execution will happen in back ground.
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
Console.WriteLine(output);
proc.WaitForExit();
}
catch (Exception ex)
{
Console.WriteLine("Exception Occurred :{0},{1}", ex.Message, ex.StackTrace.ToString());
}
}
}
Once I run I get this error though:
Exception thrown: 'System.InvalidOperationException' in System.dll
Exception Occurred :StandardOut has not been redirected or the process
hasn't started yet., at
System.Diagnostics.Process.get_StandardOutput() at
CefSharp.MinimalExample.Wpf.CallBatchFile.ExecuteBatFile() in
C:\Users\CefSharp.MinimalExamplemaster\CefSharp.MinimalExample.Wpf\CallBatchFile.cs:line
27
The batch file runs successfully, but then I'm not able to store the result into a variable. I can't get it to work in anyway. Has anyone got any suggestion?
This is my moch batch:
#echo off
cd C:\users\934874
echo.>silvio.txt
title This is your first batch script!
echo Welcome to batch scripting!
if "%errorlevel%"=="0" cls &Echo Success.
if "%errorlevel%"=="1" cls &Echo Fail
pause
The output that I'm expecting is either Success / Fail at console, and store that as a string into a variable.
Thanks in advance for your help
Need to redirect the output
proc.StartInfo.RedirectStandardOutput = true;
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx
Quoting from
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute(v=vs.110).aspx
When UseShellExecute is false, the WorkingDirectory property is not used to find the executable. Instead, it is used only by the process that is started and has meaning only within the context of the new process. When UseShellExecute is false, the FileName property can be either a fully qualified path to the executable, or a simple executable name that the system will attempt to find within folders specified by the PATH environment variable.
One of the simplest way is to make your batch file write its output to a text file. Then your main program can read the text file after the batch has finished.
If you really want to read from the standard output stream, please take a look at this other SO post:
Capturing console output from a .NET application (C#)

Process.Start() doesn't work properly

I have program pro1.exe that reads from input file, calculates result and writes it to output file.
Now I'm writing program test.exe, that tests it on different tests (fill input, run pro1 using Process.Start() and compares output with supposed)
Problem is following: after executing pro1.exe output file is empty. However, if I run it manually, it writes to output file.
Here is code how I execute pro1:
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = _applicationName;
processInfo.ErrorDialog = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
Process proc = Process.Start(processInfo);
_applicationName is a full path to exe file.
in debug I see, that process is starting, and ending without errors.
This is often caused by having a different WorkingDirectory. You likely need to set the WorkingDirectory property to match the executable's path.
Without this, when UseShellExecute == false, the working directory may not be the application's local path.

XCopy does not work with UseShellExecute = false

I am trying to run a Batch file from .net/c# using System.Diagnostics.Process. Somehow it does not execute xcopy command of the Batch file.
Sample Batch File:
#copy test to test2 including sub directories
xcopy c:\test\ c:\test2
C# code:
public void RunMSIBatchFile(string _workingDirectory, string batchFileName)
{
var process = new Process
{
StartInfo =
{
UseShellExecute = false,
RedirectStandardOutput = true,
WorkingDirectory = _workingDirectory,
FileName = _workingDirectory + batchFileName,
CreateNoWindow = true,
RedirectStandardError = true
}
};
process.OutputDataReceived += ProcessOutputDataReceived;
process.Start();
process.BeginOutputReadLine();
process.WaitForExit(Convert.ToInt32(CommandTimeOut.TotalMilliseconds));
}
If I change UseShellExecute to true then it works but then there seems to be no way to capture standard output.
Has anyone faced such problem?
I've tested your exact code, and appear to be able to receive data just fine. However, since the read occurs asynchronously, it is possible for WaitForExit(...) to return before you have read all of the data. It appears that the end of the data is signalled by the Data property of the DataReceivedEventArgs passed to the OutputDataReceived event handler being null.
It is also worth noting that if xcopy requests input from the user (e.g. in the case of a file with the same name existing in the destination) it appears that no data is returned. You may want to check for this in your batch file, or also handle data from the Standard Error stream.

Embedding an exe file in C# console?

I wish to embed an exe file (particularly "python.exe", the interpreter of Python 2.7) in my C# Console Application, meaning I want the user to enter commands, receive the interpreter's output into a string variable and use Console.WriteLine to print that output. My code so far is:
ProcessStartInfo processStartInfo = new ProcessStartInfo("C:/Python27/python.exe");
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
Process process = Process.Start(processStartInfo);
if (process != null)
{
while (true)
{
process.StandardInput.WriteLine(Console.ReadLine());
process.StandardInput.Close();
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
}
}
I can write "print 5" and get the correct output, but when writing it again I get the following error:
Cannot write to a closed TextWriter.
I believe this error is because I close the StandardInput, but without that line of code I don't get any output at all. What can I use to send multiple commands to the exe?
Thank you in advance!
Call process.StandardInput.Flush() instead. Flush makes any buffered TextWriter write all of its input to the destination, which is what's happening here - you're calling Close() which has the side effect of flushing the buffers as well as closing the stream.
See the MSDN documentation for more info.

Process.StandardOutput.ReadToEnd() and extraneous newline chars

I am trying to understand why, when I call the above function, I am getting hex 0D0A every 80th column on the output I am reading.
I have a powershell script, for testing that has two lines in it for brevity's sake:
$xmlSpew = "<IISAppPoolConfig><DefaultWebSite><ApplicationPoolName>DefaultAppPool</ApplicationPoolName></DefaultWebSite><AuthN>Basic</AuthN></IISAppPoolConfig>"
Write-Output $xmlSpew
I am calling the script using the Process object with ProcessStartInfo as follows:
var psi = new ProcessStartInfo
{
WorkingDirectory = Path.GetDirectoryName(FileToRun),
FileName = FileToRun,
Arguments = Arguments,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
};
var process = new Process
{
StartInfo = psi,
EnableRaisingEvents = true,
};
FileToRun value is:
C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
Arguments value is:
-File "C:\Program Files\MyTest\MyProgInputs\read.d\IISAppPoolConfig.ps1"
The script runs fine and I get back exit code 0, but I have this mysterious (to me) 0D0A newline every 80th char in standard out that I capture using:
var Stdout = new List<string>;
...
Stdout.Add(process.StandardOutput.ReadToEnd());
This is wreaking havoc on my XML efforts once I have standard out stored in a string var. I expected to get exactly what I write to the stdout in the ps1 script, not the extra newline.
What am I missing? I've looked for others with this issue, but I have not found an answer. Hopefully it is not me being search-challenged.
Follow this P/Invoke method and set dwXCountChars to a very large value. Don't forget to include STARTF_USECOUNTCHARS in the flags as well.
Final and tested resolution for now (because I need to ship something), is to have output from powershell come from the Write-Host cmdlet instead of Write-Output. The process for obtaining stdout remained the same as in my original post. Hope this helps others. Thanks for all the inputs.

Categories

Resources