I'm attempting to redirect output from a batch file execution to the main window of our console application.
I'm calling the method to run the process like this:
this.runProcess("\\bar\foo\blah\", "myBatch1.bat", "bat");
The method being called is as follows:
public void runProcess(string aPath,string aName,string aFiletype)
{
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Started: {0}",DateTime.Now.ToString("dd-MMM hh:mm:ss"));
Console.WriteLine("Will try run this file {0} {1}",aPath,aName);
Console.WriteLine("File type {0}",aFiletype);
string stInfoFileName;
string stInfoArgs;
if(aFiletype == "bat")
{
stInfoFileName = @"cmd.exe";
stInfoArgs = "//c " + aName;
}
else
{ //vbs
stInfoFileName = @"cscript";
stInfoArgs = "//B " + aName;
}
this.aProcess.StartInfo.FileName = stInfoFileName;
this.aProcess.StartInfo.Arguments = stInfoArgs;
this.aProcess.StartInfo.WorkingDirectory = @aPath;
this.aProcess.StartInfo.CreateNoWindow = true;
this.aProcess.StartInfo.UseShellExecute = false;
this.aProcess.StartInfo.RedirectStandardError = true;
this.aProcess.StartInfo.RedirectStandardOutput = true;
this.aProcess.Start();
Console.WriteLine("<<<got to here");
Console.WriteLine(this.aProcess.StandardOutput.ReadToEnd());
Console.WriteLine(this.aProcess.StandardError.ReadToEnd());
this.aProcess.WaitForExit(); //<-- Optional if you want program running until your script exit
this.aProcess.Close();
Console.WriteLine("Finished: {0}",DateTime.Now.ToString("dd-MMM hh:mm:ss"));
}
To try to figure out what is happening I've added extra calls to WriteLine
.
"<<<got to here"
gets written to the console then it just hangs and nothing further happens.
Suspect my mistake is something very trivial as my experience with this technology is limited.
What am I doing wrong?
Well, you're using
ReadToEnd()
- that's going to block until the process exits, basically.This is an exceptionally bad idea when you're redirecting both Standard Output and Error - when the I/O buffer gets full, both of the applications are going to freeze.
Instead, you might want to use asynchronous I/O to read the output (and write it to console as needed - you'll need to make sure the Error and Output don't mess each other up, though). Or just redirect either one of those rather than both.
The easiest way to handle this is by using
ErrorDataReceived
andOutputDataReceived
events:Apart from actually working, this also means that the output is printed out as it comes, rather than when the process exits.
I amended the first option after
if(aFiletype == "bat")
and thebat
files are running ok.Since you want the child's output in the existing console, you don't need any redirection. Just set
UseShellExecute
to false and don't setCreateNoWindow
.This code works for me:
I took out the redirection and associated logic, and the line that set
CreateNoWindow
. I also addedaPath
to the command line so that it would work for UNC paths (paths with no drive letter) since they can't be set as the working directory.