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
|