Browse DevX
Sign up for e-mail newsletters from DevX


Launching and Monitoring External Programs from VB.NET Applications : Page 5

You no longer need to use the Win32 API or the VB Shell function to launch external applications. Instead, use the System.Diagnostics.Process class built into the .NET framework to simplify your code.

Controlling Process I/O
Sometimes you want to go beyond a simple command line and send more complex input directly to a launched process. Similarly, piping the output to a file, as in the preceding example, is not always the best option. It many cases, it's much more efficient to pipe 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. To do that, when you launch the process, you set the ProcessStartInfo object's RedirectStandardInput, RedirectStandardOutput, and RedirectStandardError properties to True. Then, after launching the process, use the Process object's StandardInput, StandardOutput, and StandardError properties to assign the I/O streams to StreamReader and StreamWriter objects.

One caveat: By default, the framework uses the Win32 ShellExecute function internally to launch processes (that's how it can automatically launch the appropriate application based on the file association); but when you want to reassign the I/O streams, you must set the ProcessStartInfo.UseShellExecute property to False before starting the process. Note that when you do that, 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. For example, the following code creates an invisible window, retrieves a directory listing of the .com files in the System folder, and then displays the results in a MessageBox.

   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
   Dim sIn As StreamWriter = myProcess.StandardInput
   sIn.AutoFlush = True
   Dim sOut As StreamReader = myProcess.StandardOutput
   Dim sErr As StreamReader = myProcess.StandardError
   sIn.Write("dir c:\windows\system32\*.com" & _
   sIn.Write("exit" & System.Environment.NewLine)
   s = sOut.ReadToEnd()
   If Not myProcess.HasExited Then
   End If
   MessageBox.Show("The 'dir' command window was " & _
      closed at: " & myProcess.ExitTime & "." & _
      System.Environment.NewLine & "Exit Code: " & _
For programs that don't use StdIn, you can use the SendKeys method to input keystrokes. For example, this code launches Notepad and enters some text.

   Dim myProcess As Process = New Process()
   myProcess.StartInfo.FileName = "notepad"
   myProcess.StartInfo.WindowStyle = _
   myProcess.EnableRaisingEvents = True
   AddHandler myProcess.Exited, _
      AddressOf Me.SendKeysTestExited
   ' wait until the program is ready for input
   If myProcess.Responding Then
      System.Windows.Forms.SendKeys.SendWait( _
         "This text was entered using the " & _
         "System.Windows.Forms.SendKeys method.")
   End If
You can send any keystroke using the SendKeys method, including Alt, Ctrl, and Shift keys, which require special symbols; therefore, you can use it to save or load files, exit or perform other menu-driven commands. However, the SendKeys method only sends keys to the active window (the one that has the focus), so it can cause problems if an application loses the focus during the process. (Check the MSDN documentation topic "Sendkeys class" for more information

Be sure to give the launched process time to create its main window and display before sending keystrokes. The Process.WaitForInputIdle method causes the launching application to wait until the launched process is in an idle state, waiting for user input. The parameter is an Integer timeout value, in milliseconds. In this case, the launching program waits up to one second for the text editor to be ready for input. If by that time the program is not ready, it tests to see if it's responding before continuing, otherwise it kills the process. For some systems or applications, you would want to set the parameter to a higher value, because not all processes launch as quickly as Notepad. If you omit the timeout parameter, and the launched process never enters an idle state, your program could wait forever.

To sum up, although the Shell function is still available, the System.Diagnostics.Process class gives you more control over launching and controlling processes, as well as detecting when they exit, and getting an exit code. By redirecting StdIn, StdOut, and StdErr, you can send and receive data from applications. Using the SendKeys method, you can send input to applications that don't use StdIn, and you can force them to save data to files, where you can later read the saved data from your application.

A. Russell Jones, Ph.D. is DevX's Executive Editor. He's a former reptile keeper and professional musician who now composes computer applications. His most recent books are Mastering ASP.NET with VB.NET and Mastering ASP.NET with Visual C# (both published by Sybex). Reach him by e-mail at rjones@devx.com.
Thanks for your registration, follow us on our social networks to keep up-to-date