Launch and monitor external programs from .NET

VB6 let you launch external programs using the Shell command and you could control the launched program's window style with the windowstyle parameter.

    lngPID = Shell("c:\...\MyTextFile.txt", vbNormalFocus)

To wait for the external program to terminate you could use the WaitForSingleObject API (view the VB6 sample). In VB.NET you can use the Microsoft.VisualBasic.Compatibility namespace and still call the Shell command but there's a better way.

Launching an external program.

The System.Diagnostics namespace has a Process class you can launch external programs with. You pass in the name of an executable file or a filename with an extension associated with an executable application.

    System.Diagnostics.Process.Start("c:\...\MyTextFile.txt")

This code returns a Process object:

    Dim myProcess As Process = System.Diagnostics.Process.Start("c:\...\MyTextFile.txt")
    MessageBox.Show(myProcess.ProcessName)

An overloaded Process.Start method takes a ProcessStartInfo parameter that let's you set process initialization values such as the WindowStyle.

    Dim psInfo As New System.Diagnostics.ProcessStartInfo ("c:\...\MyTextFile.txt")
    psInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
    Dim myProcess As Process = System.Diagnostics.Process.Start(psInfo)

Or,

    Dim myProcess As System.Diagnostics.Process = new System.Diagnostics.Process()
    myProcess.StartInfo.FileName = "c:\...\MyTextFile.txt"
    myProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
    myProcess.Start

You can also do all of this through the IDE by dragging a Process component unto your form from the Components area of the Toolbar.

Start a process and wait until it exits.

To wait for a launched process to end, call the Process.WaitForExit method. Your application will stop executing until the launched process exits. However, this will cause your application to stop responding to system events, such as the Paint event.

    '   
    ' Start a new process (Notepad).
    '
    Dim myProcess As Process = System.Diagnostics.Process.Start("MyTextFile.txt")
    '
    ' Wait until it ends.
    '
    myProcess.WaitForExit()
    
    MessageBox.Show("Notepad ended: " & myProcess.ExitTime & "." & _
        System.Environment.NewLine & "Exit Code: " & myProcess.ExitCode)
    '
    ' Close the process to free resources.
    '
    myProcess.Close()

Start an invisible process.

You can start a process and get its output without a visible window. This shows how to changes to the System folder, run the DOS Dir "*.exe" command and send the output to the Output.txt file. The Windows XP command shell interpreter recognizes "&&" as a command separator, thus, you can put multiple commands on a single line. The ">>" operator redirects output into a file.

    Dim myProcess As Process = New Process()
    Dim s As String
    Dim outfile As String = Application.StartupPath & "\Output.txt" 
    '
    ' Get the System path. 
    '
    Dim sysFolder As String = 
       System.Environment.GetFolderPath(Environment.SpecialFolder.System)
    '
    ' Createe the command line. 
    '
    myProcess.StartInfo.FileName = "cmd.exe" 
    myProcess.StartInfo.Arguments = "/C cd " & sysFolder & _
        " && dir *.com >> " & Chr(34) & outfile & Chr(34) & " && exit"
    '
    ' Start the process in a hidden window.
    ' 
    myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden 
    myProcess.StartInfo.CreateNoWindow = True 
    myProcess.Start() 
    '
    ' Kill the process if it doesn't finish in one minute.
    ' 
    myProcess.WaitForExit(1000) 
    If Not myProcess.HasExited Then 
        myProcess.Kill() 
    End If
    '
    ' Show the results.
    ' 
    MessageBox.Show("The 'dir' command window was " & _
        "closed at: " & myProcess.ExitTime & "." & System.Environment.NewLine & _
        "Exit Code: " & myProcess.ExitCode) 
    
    myProcess.Close() 

Determine when a process exits.

The Process class can raise an Exited event when a process ends. You must set the Process.EnableRaisingEvents property True and create an event handler.

    myProcess.EnableRaisingEvents = True
    '   
    ' Add an event handler.
    '
    AddHandler myProcess.Exited, AddressOf Me.ProcessExited
   
    myProcess.Start()
   
    '
    ' Event handler.
    '
    Friend Sub ProcessExited(ByVal sender As Object, _
            ByVal e As System.EventArgs)

        Dim myProcess As Process = DirectCast(sender, Process)

        MessageBox.Show("The process exited, raising " & _
            "the Exited event at: " & myProcess.ExitTime & _
            "." & System.Environment.NewLine & "Exit Code: " & myProcess.ExitCode)

        myProcess.Close()
    End Sub

Note, if the launched process hangs your application will too.

Controlling process input/output.

You may need to send input directly to a launched process and send the output directly back to your program. For programs that use StdIn, StdOut, and StdErr, such as console applications, you can override the defaults and provide a StreamWriter to write input and StreamReaders to read the StdOut and StdErr outputs.

.NET uses the Win32 ShellExecute function to launch processes so when you want to reassign I/O streams, you must set the ProcessStartInfo.UseShellExecute property False before starting the process. Also, you must either specify the full path to the file, or the file location must be in the environment path string or in one of the places Windows searches for files.

    Dim myProcess As Process = New Process()
    Dim s As String myProcess.StartInfo.FileName = "cmd.exe"
    
    myProcess.StartInfo.UseShellExecute = False
    myProcess.StartInfo.CreateNoWindow = True 
    myProcess.StartInfo.RedirectStandardInput = True 
    myProcess.StartInfo.RedirectStandardOutput = True
    myProcess.StartInfo.RedirectStandardError = True
    myProcess.Start() 

    Dim sIn As StreamWriter = myProcess.StandardInput 
    Dim sOut As StreamReader = myProcess.StandardOutput 
    Dim sErr As StreamReader = myProcess.StandardError
 
    sIn.AutoFlush = True 
    sIn.Write("dir c:\windows\system32\*.com" & System.Environment.NewLine) 
    sIn.Write("exit" & System.Environment.NewLine) 
    s = sOut.ReadToEnd()
 
    If Not myProcess.HasExited Then 
        myProcess.Kill() 
    End If 

    MessageBox.Show("The 'dir' command window was " & _
        closed at: " & myProcess.ExitTime & "." & _ 
        System.Environment.NewLine & "Exit Code: " & myProcess.ExitCode) 

    sIn.Close() 
    sOut.Close() 
    sErr.Close() 
    myProcess.Close() 
    MessageBox.Show(s) 

For programs that don't use StdIn, you can use the SendKeys method to input keystrokes.

    Dim myProcess As Process = New Process()

    myProcess.StartInfo.FileName = "notepad"
    myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal
    myProcess.EnableRaisingEvents = True

    AddHandler myProcess.Exited, AddressOf Me.SendKeysTestExited
    myProcess.Start()
    '   
    ' Wait until the program is ready for input.
    '
    myProcess.WaitForInputIdle(1000)

    If myProcess.Responding Then
        System.Windows.Forms.SendKeys.SendWait( _
                "This text was entered using SendKeys.")
    Else
        myProcess.Kill()
    End If



About TheScarms
About TheScarms


Sample code
version info

If you use this code, please mention "www.TheScarms.com"

Email this page


© Copyright 2024 TheScarms
Goto top of page