Question Displaying DOS command erroroutput in a textbox

wjburke2

Active member
Joined
Feb 3, 2009
Messages
29
Programming Experience
Beginner
I know this has been discussed a million times and I have a working program. I am allowing users to execute .bat file from a GUI. My application is simple it has a form with a split container with a list of bat file on one side and a textbox on the other. When the user clicks on a batch file the application submits it to DOS and displays the output and errors in the textbox. My problem is if I put a command that will cause an error in the first line (eg. DIRP) the error shows in the textbox "DIRP is not a valid DOS command" but if it is the last line of the bat file nothing is displayed. My concern is that the application is not getting the error if it occurs on the last command. Has anyone had experience with this and is there a solution that would insure the error is displayed. Thanks in advance for all your help.

VB.NET:
Imports System.IO

Public Class Form1

    Public StartPath As String = "\\my\ExstreamGMS\VM\Prod_Bat\"

    Sub New()

        InitializeComponent()

        ListBox1.Items.Clear()

        Dim fList As String() = Directory.GetFiles(StartPath)
        For Each f As String In fList
            ListBox1.Items.Add(Path.GetFileName(f))
        Next

    End Sub

    Sub Go(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.DoubleClick

        Dim psi = New ProcessStartInfo()
        With psi
            .FileName = StartPath & Me.ListBox1.SelectedItem
            .WorkingDirectory = "C:\"
            .CreateNoWindow = True
            .UseShellExecute = False
            .ErrorDialog = False
            .RedirectStandardOutput = True
            .RedirectStandardError = True
        End With

        Dim p As New Process With {.StartInfo = psi, .EnableRaisingEvents = True}
        AddHandler p.OutputDataReceived, AddressOf HelloMum
        AddHandler p.ErrorDataReceived, AddressOf HelloMum

        p.Start()
        p.BeginOutputReadLine()
        p.BeginErrorReadLine()

    End Sub

    Sub HelloMum(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
        UpdateTextBox(e.Data)
    End Sub

    Private Delegate Sub UpdateTextBoxDelegate(ByVal Text As String)
    Private Sub UpdateTextBox(ByVal Tex As String)

        If Me.InvokeRequired Then
            Dim del As New UpdateTextBoxDelegate(AddressOf UpdateTextBox)
            Dim args As Object() = {Tex}
            Me.Invoke(del, args)
        Else
            TextBox1.Text &= Tex & Environment.NewLine
            TextBox1.Select(TextBox1.TextLength, 0)
            TextBox1.ScrollToCaret()
        End If
    End Sub

End Class
 
My problem is if I put a command that will cause an error in the first line (eg. DIRP) the error shows in the textbox "DIRP is not a valid DOS command" but if it is the last line of the bat file nothing is displayed
Are you sure? When you write both OutputDataReceived and ErrorDataReceived to same textbox the output lines of these will be mixed. If the command output is long it is likely that you'll find the two error lines mixed in somewhere at the beginning of output. Here's an excerpt of such output, with lines tagged where they come from (my .bat file had one DIR command followed by one DIRP command):
OUT: 18.11.2014 19:51 <DIR> .
OUT: 22.10.2014 22:31 <DIR> ..
OUT: 06.09.2014 03:27 768 000 SQLite.Interop.dll
OUT: 18.11.2014 19:51 <DIR> go
OUT: 17.06.2014 23:21 772 genre.xml
ERR: 'xdir' is not recognized as an internal or external command,
OUT: 25.06.2013 22:35 764 pgrid.xsd
ERR: operable program or batch file.
OUT: 10.11.2012 12:56 376 data.xml
ERR:
OUT: 17.11.2012 14:09 42 append.txt
 
Very good catch, You are right as I look back through the output I see the error messages are mixed with the standard output. I guess it confused me because the commands are listed in the proper order. How do I make it wait for the first command to finish before submitting the next? This will be a real issue when it comes to submitting that actual batch files that run a program to create files then copy the files to a watch directory. If the program that creates the files isn’t finished the copy will fail. This process works when the user just clicks on the batch file. A new server configuration has caused us have to create a program to submit the batch files through a dashboard instead of the user just clicking on it. Is there a way to have it wait and still show realtime standard output.
 
You need two textboxes, one for OutputDataReceived and one for ErrorDataReceived. Output will be sequential for each, but it is impossible to synchronize the output of the two to one textbox. Your application is not in control of the batch command processing and its output, that is done by the Windows command shell.

If the batch has statements that fails the operation will not complete successfully, only way to cater for that is by including error handling in the batch script itself. From your application you can check ExitCode property of process when it has exited. You should add event handler for its Exited event in any case, where you should remove event handlers and dispose the Process that you created.

ExitCode is by default 0 for success and other number for failure, but for a batch script it will return the exit code of last statement (ie useless), the batch script can be written to return custom exit codes. You need a carefully written batch script to get any usable error handling and reporting with it.
 
Thank you JohnH I will look into the DOS error handling. I am not sure if people that create the batch files will know what needs to be done. The other alternative would be to find a way to submit the batch commands individually. I played with this idea in the beginning but I think I had similar issues so decided to go this route. Do you have any advice or can you point me in the direction of information on submitting the batch commands to DOS. BTW thank you for for your advise and your time. I will look into customizing the error routine. Here is what I an submitting a command that I need to wait to finish and one or more copy commands.

D:\Exstream_Engine\ProdEngine -controlfile=\\o2nas1\ExstreamGMS\Control\CoTray30_FLUP_cntl.opt
copy "\\myserver\ExstreamGMS\COTRAY\X159_1132_ADFLP_Proc_Report.txt" "\\myserver\WebPress\Web1\CoTray\X159\X159_1132_ADFLP_Proc_Report.txt"
 
Last edited:
You could read the .bat file as a lines array, and execute each line (for example as a temp.bat, or parse each line and figure out the equivalent .Net operation like IO.File.Copy).
 
Back
Top