PowerShell: How to execute and manage external processes
- select the contributor at the end of the page -
While it’s not recommended to use external utilities in PowerShell, sometimes you have no choice. Of course, it’s always a good idea to first ensure that PowerShell cannot natively perform the task you have, as this eliminates dependencies and makes your scripts easily portable. Still, desperate times call for other measures. Thankfully, PowerShell offers a few different ways to execute external processes that allow you to better control their execution. Let’s cover some of these methods.
Using a simple ampersand is by far the easiest way to start execution of a EXE process. This is similar to the batch file, in that you simply kick off the EXE and let it do its thing. To start notepad.exe, for example, you’d just need to create a script and add an ampersand before the path to the EXE:
This works, but the downside is you have no control over the output. You are at mercy to however the EXE wants to behave. Good scripts control every piece possible. This is not the recommended way to kick off an external process.
Using WMI with the CreateProcess() method
Another way to kick off an external process is by using the CreateProcess()method on the Win32_Process WMI class. Prior to PS remoting, this was a great way to kick off a process on a remote computer (although it could just as easily be done on a local computer). To execute a process in this manner you’d need to invoke the CreateProcess()method and use the EXE name as the parameter. One way to invoke WMI methods is through the Invoke-WmiMethod cmdlet. This cmdlet provides a Class parameter, the name of the method you’d like to invoke and, finally, an ArgumentList parameter in which you can pass the name of the EXE:
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList 'notepad.exe'
You can see that this provides useful information such as ReturnValue. Using the return value, I could then have some logic in my script to ensure the process completed successfully (typically with a 0 return code) or not, and then make decisions based on that.
Start-Process is probably the most common way to invoke external processes in PowerShell. Start-Process provides plenty of functionality built in, such as getting the return value like the CreateProcess() method. However, it can also store the output the process generates such as stdout and stderr into a file so that you can read these files with code and perform further tasks on the output. Start-Process can also control the windows. Let’s say you’ve got a software install that pops up an annoying box while it’s installing. With Start-Process you can hide this window from your user. It also gives you the option to hide the cmd.exe window that typically pops up when executing an external process in PowerShell. At it’s most basic, you can kick off ipconfig.exe simply by using the FilePath parameter:
Start-Process -FilePath C:\Windows\System32\ipconfig.exe
However, you’d notice that a cmd.exe window pops up. I’d like to hide that:
Start-Process -FilePath C:\Windows\System32\ipconfig.exe -NoNewWindow
It then puts the standard output directly to the PowerShell session.
Another cool trick with Start-Process is redirecting output to a file. Simply use the RedirectStandardOutput parameter.
Start-Process will most likely apply to nearly all of the times you need to execute external processes in PowerShell. However, if you need even further control, you can also dive into .NET and tinker around with the Process class. Using .NET gives you the most control but it’s also the most complicated.
As you can see, there are a few different ways you can spawn external processes in PowerShell. Depending on the context, you may find yourself using each on occasion. Always be sure to understand all your options so you can make the best choice.