I have a windows form that executes a batch file. I want to transfer everything that happends in my console to a panel in my form. How can I do this? How can my DOS console
I'm pretty sure there are better options but you can route the output of the command to a temp file
Redirecting Command-Line Output to Files
For programs that display a lot of text, consider redirecting text that is usually displayed on stdout to a file. Displaying a lot of text will slow down execution; scrolling text in a terminal window on a workstation can cause an I/O bottleneck (increased elapsed time) and use more CPU time.
The following commands show how to run the program more efficiently by redirecting output to a file and then displaying the program output:
myprog > results.lis more results.lis Redirecting output from the program will change the times reported because of reduced screen I/O.
I think you could just route it to a variable as well, not 100% sure though. There's probably far better options but at least this is one.
I recently build a tiny app where I was interacting with batch files. I found this snippit of code that allowed me to do this:
Process proc = new Process
{
StartInfo =
{
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
}
};
proc.Start();
string errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();
string outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
From here, just direct those strings into a usercontrol of your choice.
EDITS
Note: This is not a general solution. It can lead to deadlocks. From the doc for RedirectStandardError:
Synchronous read operations introduce a dependency between the caller reading from the StandardError stream and the child process writing to that stream. These dependencies can cause deadlock conditions. When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits for the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits for the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait for each other to complete an operation, and neither can continue. You can avoid deadlocks by evaluating dependencies between the caller and child process.
You can call the DOS or batch program from your Form application and redirect the output to a string:
using (var p = new System.Diagnostics.Process( ))
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = PathToBatchFile;
p.StartInfo.Arguments = args;
p.Start( );
string o = p.StandardOutput.ReadToEnd( );
p.WaitForExit( );
}
The doc states that if you want to read both StandardError and StandardOutput, you need to read at least one of them asynchronously in order to avoid deadlocks.
Also, if you call ReadToEnd on one of the redirected streams, you must do so before calling WaitForExit(). If you WaitForExit before ReadToEnd, the output buffer can fill up, suspending the process, which means it will never exit. That would be a very long wait. This is also in the doc!
example:
string output;
string error;
System.Diagnostics.Process p = new System.Diagnostics.Process
{
StartInfo =
{
FileName = program,
Arguments = args,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
UseShellExecute = false,
}
};
if (waitForExit)
{
StringBuilder sb = new StringBuilder();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
Action<Object,DataReceivedEventArgs> stdErrorRead = (o,e) =>
{
if (!String.IsNullOrEmpty(e.Data))
sb.Append(e.Data);
};
p.ErrorDataReceived += stdErrorRead;
p.Start();
// begin reading stderr asynchronously
p.BeginErrorReadLine();
// read stdout synchronously
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
// return code is in p.ExitCode
if (sb.Length > 0)
error= sb.ToString();
}
You should start off by adding a reference to System.Diagnostics
, then calling the batch file like this:
string myFile = "c:\\path\\to\\batch_file.bat";
ProcessStartInfo psi = new ProcessStartInfo(myFile);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
Process proc = Process.Start(psi);
Now, if you want the call to be blocking (I.E., your application will freeze until the file is done), then just use string result = proc.StandardOutput.ReadToEnd()
to read the entirety of your batch file's output.
However, if you want to have the application continue to respond, as well as display output in real-time, then you'll need to have to use BeginOutputReadLine.
I've been fooling around with the System.Diagnostics.Process class for calling console based applications and formating and returning the output. I think it will work with Batch files, as well. I'll take a moment here to test that. Here is some sample code:
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo();
start.UseShellExecute = false;
start.RedirectStandardInput = true;
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
start.RedirectStandardOutput = true;
start.FileName = "at";
System.Diagnostics.Process myP = System.Diagnostics.Process.Start(start);
String strOutput = myP.StandardOutput.ReadToEnd();
if (strOutput.Contains("There are no entries in the list."))
{
litMsg.Text = "There are no jobs";
}
else
{
strOutput = strOutput.Replace("\r", "");
foreach (String line in strOutput.Split("\n".ToCharArray()))
{
//(0,7) (7,5)(12, 24) (36, 14) (50, )
//Status ID Day Time Command Line
//-------------------------------------------------------------------------------
// 1 Tomorrow 3:00 AM dir *
if (line.Length > 50)
{
String Status = line.Substring(0, 7);
String ID = line.Substring(7, 5);
String Day = line.Substring(12, 24);
String Time = line.Substring(35, 14);
String Command = line.Substring(49);
}
}
}