Prof. Powershell

Start-Process Cmdlet: The Best of Both Worlds

Sometimes the standby command-line or resource kit tools work best. Still, there is a way to use information from those tools with further processing in PowerShell and this command helps.

Even though I enjoy using PowerShell and am constantly finding new ways to apply it, sometimes the old school ways are still best. There's nothing wrong with the use of legacy command-line or resource kit tools. If they do the job why stop using them? The challenge is finding a good way to use them in PowerShell. Of course you can run any command in PowerShell, but what if you want to keep track of the output or errors? This is a bit more difficult because the command isn't writing objects to a pipeline.

What you can do is use the Start-Process cmdlet. For example, if you run this command, you'll see the results, but in a new window:


PS C:\> start-process tracert -ArgumentList "-d -4 mcpmag.com"

If you don't like the window, you can minimize it with the WindowStyle parameter, or even hide it:

PS C:\> start-process tracert -ArgumentList "-d -4 mcpmag.com" -WindowStyle minimized

Or if you prefer, you can "keep" the results in your current PowerShell window with the -NoNewWindow parameter:

PS C:\> start-process tracert -ArgumentList "-d -4 mcpmag.com" -NoNewWindow

But it gets even better. We can send the output, both success and errors to different files:

PS C:\> start-process tracert -ArgumentList "-d -4 mcpmag.com" -RedirectStandardOutput e:\trace.txt -RedirectStandardError e:\tracerr.txt-NoNewWindow

Here's a more production-worthy example. You want to audit all the scheduled tasks on a group of computers. The SCHTASKS.EXE command-line utility is perfect. It can query a remote machine and write output in a CSV format. If we can save it to a file we can re-import it into PowerShell as objects for further analysis. Here's what this one-line command might look like:

Get-content c:\files\computers.txt | foreach { start-process schtasks -ArgumentList "/query /v /s $_ /fo csv" -NoNewWindow -RedirectStandardOutput "e:\$_-tasks.csv" -RedirectStandardError "e:\$_-err.txt" }

While technically not a background job, this command is running in the background so you get your prompt back right away. If you prefer to wait, then tell Start-Process with -Wait. Personally, I'd rather get back to work and check the files later.

There are some limitations. The redirection only works per command, so in this example I have to have separate result and error files for each computer. If I want a single error file, I could combine the files:

PS C:\> dir e:\*-err.txt | where {$_.length -gt 0} | get-content | out-file e:\errsum.txt

I strongly encourage you to take the time to read the full help and examples for Start-Process. There's much more than what I have presented here and you never know what might spark an idea.


About the Author

Jeffery Hicks is a Microsoft MVP and an IT veteran with almost 20 years of experience, much of it spent as an IT consultant specializing in Windows server technologies. He works today as an independent author, trainer and consultant. His latest book is Managing Active Directory with Windows PowerShell 2.0: TFM (SAPIEN Press 2011). Follow Jeff on Twitter and on his blog.

Reader Comments:

Thu, Dec 8, 2011 Frank Peter Schultze Germany

Under the hood, Start-Process leverages the methods and properties of System.Diagnostics.Process. The Start-Process cmdlet's PassThru switch provides access to the process and enables you to use methods like WaitForExit(Int32) that instructs the component to wait the specified number of milliseconds for the associated process to exit: $proc = Start-Process .... -PassThru $Exit = $proc.WaitForExit(60000) if (!$Exit) { Write-Error "Process is still running after 60 seconds" }

Add Your Comment Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above