Processes
Start a New Process
Starting a new process consists of constructing and initializing an instance of CreateProcessInfo, followed by passing the newly constructed instance to one of the Process constructors.
At its most basic, creating an new process is as follows. This code creates a new instance of notepad.exe
.
using (var process = new Process(new CreateProcessInfo {
FileName = "notepad.exe"
})) {
// the new process continues to run even after the process
// variable is disposed.
}
Settings for the New Process
Choosing the executable and arguments for a process is done through the CreateProcessInfo class. The properties of the CreateProcessInfo class are nearly identical to System.Diagnostics.ProcessStartInfo properties.
The FileName property indicates the name of executable image. The Arguments and ArgumentsList properties are used to provide arguments for the new process.
Only one of Arguments and ArgumentsList may be used. The contents of Arguments is passed as the command line arguments to the new process exactly as-is. The elements of ArgumentsList are escaped according the requirements of CommandLineToArgvW and join by space separators.
You may further control how the new process is created by passing a set of ProcessOptions flags to Process(CreateProcessInfo, ProcessOptions). For example, you may use ProcessOptions.Suspended to create the new process in a suspended state.
Handle Inheritance
Handle inheritance operates different when creating a new process with the Process class. Unlike System.Diagnositcs.Process inheritable handles are not automatically inherited by the child process. Only handles listed in a InheritHandlesAttribute instance added to CreateProcessInfo.Attributes are inherited by the new process.
var createProcessInfo = new CreateProcessInfo {
FileName = "process.exe",
Attributes = {
new InheritHandleAttribute {
HandleOne,
HandleTwo,
HandleTree
}
}
};
The process created with the createProcessInfo
settings above will inherit handles HandleOne
, HandleTwo
and HandleThree
. The handles must be marked as inheritable.
Exception to the Rule
When CreateProcessInfo.UserName handle inheritance reverts to inheriting all inheritable handles from the current process. The Windows CreateProcessWithLogonW API does not support STARTUPINFOEX.
Wait for a Process to Exit
Use the Process.Exited property to determine when a process has exited. Process.Exited property returns Task<int>
that completes when the process has exited.
If the Process is disposed before the underlying process exists, the Process.Exited task is transitioned to a canceled state.
Redirect Standard Output
The CreateProcessInfo class provides three properties to enable I/O redirection: RedirectStandardInput, RedirectStandardOutput and RedirectStandardError. Set one or more of these properties to true
to enable I/O redirection for the new process.
Once the new process has started, you may use the Process's class StandardInput, StandardOutput or StandardError properties to access the redirected streams. Be aware that accessing more than one stream in a synchronous manner may lead to a deadlock.
Asynchronous Reading
Rather than using the StandardOutput or StandardError, you may use BeginReadingStandardOutputAsync(Boolean) or BeginReadingStandardErrorAsync(Boolean).
Using BeginReadingStandardOutputAsync(Boolean) or BeginReadingStandardErrorAsync(Boolean) along with OutputDataReceived and ErrorDataReceived events enables asynchronous reading of the redirected streams.
Both BeginReadingStandardOutputAsync(Boolean) and BeginReadingStandardErrorAsync(Boolean) return a Task
instance that completes when no more data will be read from the underlying stream. If Dispose() is called before the streams complete reading, the Task
will be transitioned to an canceled state.