C# Windows Form .Net and DOS Console

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);
        }
    }
}