How to show the output of a *.bat or *.cmd file in a WPF application, without waiting for the *.bat file to end
Notes
-
The functions
– process.StandardOutput.ReadToEnd();
– process.StandardOutput.Read();
– process.StandardOutput.ReadLine();
will wait for the process to end and then output the result. -
If you want to show the output during processing, you should use
– process.OutputDataReceived += new DataReceivedEventHandler(ProcessOuputHandler);
– and process.BeginOutputReadLine(); -
Because the BeginOutputReadLine will spawn a new thread, you can’t access the UI directly. If you want to update a textbox, you should use the control.Dispatcher.Invoke function.
-
With the control.Dispatcher.CheckAccess() you can determine if the functions is called from the UI thread or not.
-
[myWpfWindow] is a WPF window containing a textbox with the name [outputTextBox] and a button with the name [testButton].
-
The function [ShowingOutputOfBatFile] is called from a [testButton] click eventhandler
public void ShowingOutputOfBatFile() { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = @"C:\Temp\Test.bat"; startInfo.Arguments = "firstParameter secondParamter"; startInfo.RedirectStandardError = true; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; startInfo.WorkingDirectory = @"C:\Temp"; // Use startInfo.CreateNoWindow = HideWindow; if you want to hide the window using (Process process = new Process()) { process.StartInfo = startInfo; process.OutputDataReceived += new DataReceivedEventHandler(ProcessOuputHandler); process.Start(); process.BeginOutputReadLine(); while (!process.HasExited) { // Refresh you're WPF window here myWpfWindow.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate); Thread.Sleep(1000); } } } public void ProcessOuputHandler(object sendingProcess, DataReceivedEventArgs outLine) { if (!String.IsNullOrEmpty(outLine.Data)) { if (!outputTextBox.Dispatcher.CheckAccess()) { // Called from a none ui thread, so use dispatcher ShowLoggingDelegate showLoggingDelegate = new ShowLoggingDelegate(ShowLogging); outputTextBox.Dispatcher.Invoke(DispatcherPriority.Normal, showLoggingDelegate, outLine.Data); } else { // Called from UI trhead so just update the textbox ShowLogging(outLine.Data); }; } } private delegate void ShowLoggingDelegate(string text); private static Action EmptyDelegate = delegate () { }; /// <summary> /// Show the logging on screen /// </summary> /// <param name="text"></param> private void ShowLogging(string text) { myWpfWindow.outputTextBox.AppendText(text); myWpfWindow.outputTextBox.ScrollToEnd(); }