I recently had the need to script the execution of a command-line utility and thought it would be a good learning experience to try doing it with PowerShell. The utility would sometimes output to the STDOUT, but would also send its output to STDERR if there was a problem. This seemed to involve many different problems all at once including:
- Running an EXE with a space in the path and multiple command-line parameters
- Capture both STDERR and STDOUT to a variable
- Escaping special characters/using special characters
- Doing string concatenation
- Doing explicit type conversion
- Sending an email
- Joining a string array to a single string variable
- Doing a "FOR" loop (optional but fun).
Anyway, here's the script I came up with that runs a command-line app and takes all the output (including the error stream) and joins it into a string and then sends it in an email to me. It's a bit ugly because I am a PowerShell novice, but it does work. The only trouble I've noticed is that sometimes the error lines will be a bit out of sequence from the corresponding stdout lines. If someone knows how to fix that, please let me know in the comments!!!
#Setup the command string - notice the `" to escape the double-quotes inside the string (deals with spaces in path)
# and the old batch file trick of doing 2>&1 to ensure STDERR is piped to STDOUT.
$command = "& `"C:\Users\myprofile\Documents\visual studio 2010\Projects\TestOutput\TestOutput\bin\Debug\testoutput.exe`" someparameter -xyz someotherparameter -abc someotherthing -rfz -a somethinghere 2>&1"
#Execute the command and put the output in an array.
$console_output_array = invoke-expression $command
#loop through the array and print out the results to the command line (optional)
for ($i=0; $i -lt $console_output_array.length; $i++)
{
[string]$i + "=<" + $console_output_array[$i] + ">"
}
#create a single string by joining together the array
$console_output_string = [string]::join("`r`n",$console_output_array)
#send an email with the results
$emailFrom = "fromemail@example.com"
$emailTo = "toemail@example.com"
$subject = "Email subject goes here"
$smtp = new-object Net.Mail.SmtpClient("yoursmtpserver.example.com", 25)
$smtp.Send($emailFrom, $emailTo, $subject, $console_output_string)