PowerShell is the new command line interface for Windows. It allows you to automate tasks and scripts in a central console with maximum flexibility, thanks to its scripting language. Learn how PowerShell can be your best friend when it comes time to start or manage a brand-new project!.
The “start-process” is a command that allows you to start a new process. It can be used in PowerShell.
To comprehend why Start-Process and all of these other instructions are restricted, you must first comprehend how an EXE file works. When you launch an EXE file, it does whatever it was supposed to do: it pings something (ping), installs software (setup), searches up DNS records (nslookup), and so on. Start-Process and other commands to start a process work fine for this phase. It’s straightforward. When that EXE generates some output, the restriction arises.
We can start a process in PowerShell many different ways. We’ve got the PowerShell Start-Process and Invoke-Expression cmdlets, we can call the executable directly or use the ampersand (&) to invoke expressions. The most common way is to use Start-Process because it’s probably the most intuitive. PowerShell is known for it’s intuitive approach to command naming and Start-Process is an excellent choice. However, that command is limited.
A notion of standard streams exists in an EXE file, as it does in many other executable files that aren’t exclusive to Windows. Executable files return output using standard streams. There are three types of streams: stdin, stdout, and stderr. Stdin is a stream that can be supplied into the executable, but we’re not going to talk about it right now. Stdout is the stream via which the executable sends non-error output.
Think about stdout as the output of Write-Output in PowerShell. If an error happens (depending on whether the executable’s creator coded it appropriately), the executable should print it to stderr. This is a stream that will be used to return any error data.
Users of these executable files may tell what is normal output and what is an error by looking at these streams. Streams have existed for decades, and Windows PowerShell is well aware of them, having adopted their own.
Codes of Exit
Another age-old idea that executable files obey is an exit code, return code, or outcome code. When an executable quits, an exit code is a number that enables the executable to notify the user of its status.
There are some standard Codes of Exit that programs are supposed to follow like if the exit code is 0, everything is fine, exit code 3010 means it needs a reboot and so on. PowerShell can capture this exit code a few different ways like using the $LastExitCode automatic variable. Codes of Exit are another method that the executable file communicates to the user.
Capturing Streams and Codes of Exit
Let’s use an example now that you know what we’re talking about. I’ll use the good ol’ ping.exe to keep things simple. I’ll start by pinging google.com, which will return a positive response. Here, we’re not utilizing the PowerShell start process.
PS C:> ping google.com Pinging google.com [2607:f8b0:4004:80b::200e] with 32 bytes of data: Reply from 2607:f8b0:4004:80b::200e: time=61ms Reply from 2607:f8b0:4004:80b::200e: time=65ms Reply from 2607:f8b0:4004:80b::200e: time=80ms Reply from 2607:f8b0:4004:80b::200e: time=78ms Ping statistics for 2607:f8b0:4004:80b::200e: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 61ms, Maximum = 80ms, Average = 71ms PS> $LastExitCode 0 PS> $? True
I’m going to ping a host that can’t resolve a DNS name and will thus fail. Take note of $LastExitCode’s value.
PS> ping googlllll.com Ping request could not find host googlllll.com. Please check the name and try again. PS> $LASTEXITCODE 1
You saw that the exit code changes since the ping result was different, but you didn’t see streams because PowerShell doesn’t recognize the difference between executable files natively. The wording in the console is white, rather than the familiar red error messages.
We can capture the streams and redirect to files a few different ways like using > and 2> like below. This is the old school way.
PS> ping googllll.com > output.msg 2> output.err PS> Get-Content .output.err PS> Get-Content .output.msg Ping request could not find host googllll.com. Please check the name and try again.
Even when ping.exe returns a 1 (as seen above), the output is still sent to stdout in this scenario. This is a regular situation. The developer has total control over the stream and exit code that is returned, which regrettably comes in a variety of formats.
You could use Start-Process and the -RedirectStandardError and -RedirectStandardOutput arguments to use the “old school” route, but they’d still go to files.
You can see that starting a process and returning some common output isn’t too common. On top of that, PowerShell doesn’t handle the streams and Codes of Exit too well. If I were to use Start-process to run ping.exe and want to track what happened in the result I’d have to do something like this every time I wanted to run an executable file.
PS> Start-Process -FilePath -NoNewWindow ping -ArgumentList ‘google.com’ -RedirectStandardOutput output.txt -RedirectStandardError err.txt PS> $LastExitCode PS> Get-Content -Path output.txt PS> Get-Content -Path err.txt
I’m still not getting my error message!
Let’s get things sorted out. Invoke-Process is a little function I wrote that you may find in the PowerShell Gallery.
PS> Install-Script ‘Invoke-Process’ PS> . Invoke-Process.ps1
Run ping with a valid host to observe what happens.
51 ping ping ping ping 48 ping ping ping 49 phish ik ping ping ping nginx ping ping ping ping ping ping Gili ping ping ping ping ping ping ping ping ping ping
Take note of how we reach the same result. This is fantastic!
Now use an invalid host to ping.
51 ping ping ping ping 48 ping phish ping 49 ping 47 ping ping ping nginx Kunming Gili ping ping ping ping ping ping ping ping ping ping ping ping ping ping Jellyfish 457 ping ping ping
Now observe how, if anything goes wrong, we receive the standard red error messages. Under the hood, Invoke-Process utilizes Start-Process to collect stdout, stderr, and the exit code, and then transfers the output to the appropriate stream. That’s the way it should be!
Too bad PowerShell didn’t make it easier to work with streams and Codes of Exit from executable files, but I suppose nowadays, we can add that in there now that it’s open source!
The “start-process with arguments” is a PowerShell script that can be used to start processes with arguments. This script can be used in the same way as the standard Windows command line “start”.
- start-process powershell with arguments
- powershell start-process vs &
- powershell start-process in background
- powershell start-process output
- start-process powershell -verb runas