views:

100

answers:

2

I know Powershell has background job functionality with Start-Job, Wait-Job, etc., but is it possible to use the Process class from System.Diagnostics in .Net to achieve the same thing? If so, what would be the best way to do it/what advantages would it have over the default Powershell mechanism of running background jobs?

A: 

This isn't elegant or well documented. It creates a System.Diagnostic.Process object and performs some common initializations on it. Once you get the Process object, you can perform additional adjustments on it, then call Process.Start to start the process.

function New-Process($cmd, $arguments, [switch]$stdout, [switch]$stdin, [switch]$stderr, [switch]$shellexec, [switch]$showwindow)
{
    $process = New-Object "System.Diagnostics.Process"
    $startinfo = New-Object "System.Diagnostics.ProcessStartInfo"

    $startinfo.FileName = $cmd
    $startinfo.Arguments = $arguments
    $startinfo.WorkingDirectory = $pwd.Path
    $startinfo.UseShellExecute = $shellexec
    $startinfo.RedirectStandardInput = $stdin
    $startinfo.RedirectStandardOutput = $stdout
    $startinfo.RedirectStandardError = $stderr

    if (!$showwindow) {
        $startinfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
    }

    $process.StartInfo = $startinfo

    return $process
}
OldFart
A: 

You can certainly use the Process object to "start" the executable asychronously and with the process object you get back you can test to see if the EXE is done or kill the process. The trick is getting the output and error stream information back without interfering with the console while the program is runnng so you can do other stuff. From the MSDN docs, it looks like using the BeginOutputReadLine might do the trick:

// Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "Write500Lines.exe";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

Although if you want the background behavior you would need to perform the StandardOutput.ReadToEnd() on a background thread and then create a mechanism to retrieve that output from the main console thread which seems like a lot of work and at the moment I can think of any advantages over PowerShell background jobs.

Another approach is to create a runspace to do the bg job work as this blog post by Jim Truher points out.

Keith Hill