I'm using PowerShell to launch an app called GoodSync to perform a backup for me. At the end of the process, I have it email me the results. I also like to (sometimes) watch the PowerShell window to keep an eye on it and watch the status of the backup while it's processing. As my code sits right now, the stdout is going to console and that's it.
My question: Is it possible to have stdout go to console, AND save it to a variable for later processing?
You can see I'm trying something with the $output variable, but getting nowhere. Here's the error $output is returning:
You cannot call a method on a null-valued expression.
At GoodSync.ps1:119 char:42
+ $output = $proc.StandardOutput.ReadToEnd <<<< ()
+ CategoryInfo : InvalidOperation: (ReadToEnd:String) [], Runtime
Exception
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At GoodSync.ps1:120 char:42
+ $output += $proc.StandardError.ReadToEnd <<<< ()
+ CategoryInfo : InvalidOperation: (ReadToEnd:String) [], Runtime
Exception
+ FullyQualifiedErrorId : InvokeMethodOnNull
Here's my code:
(And to be a little proactive from all you gurus out there, yes I'm doing a lot with this code to output to both a file and stdout so I can keep an eye on everything. This section is just a snippet of the whole file.)
###############################
## Call the GoodSync process ##
###############################
# This is the section taken from http://stackoverflow.com/questions/8925323
# This is a known working section. However, right now I don't know how to save the stdout to variable and insert into email log file.
$procInfo = New-Object System.Diagnostics.ProcessStartInfo
$procInfo.FileName = "C:\Program Files\Siber Systems\GoodSync\gsync.exe"
$procInfo.UseShellExecute = $false
$procInfo.Arguments = '/progress=yes /exit sync MyBackupJobName'
$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $procInfo
$proc.Start() | Out-Host
(Get-Date -format T) + " - Loaded gsync.exe. Backup process running. Please stand by..." | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
$proc.WaitForExit()
(Get-Date -format T) + " - Backup complete and gsync.exe has exited." | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
# Now we take the exit code, write it to console and log file, and begin to build our email report.
if ($proc.ExitCode -eq 0) {
"Success: GoodSync Reported: Analyze or Sync Successfully Completed." | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
$subject = $RoboLog
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
} elseif ($proc.ExitCode -eq 1) {
"Failure: GoodSync Error: Analyze had Terminal Errors. Did gsync.exe close abruptly?" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
$subject = $RoboLog
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
} elseif ($proc.ExitCode -eq 2) {
"Failure: GoodSync Error: Sync had Terminal Errors. Did gsync.exe close abruptly?" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
$subject = $RoboLog
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
} else {
"Failure: GoodSync Error: General Error. Check log file." | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
$subject = $RoboLog
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
}
# Grab the stdout and stderr to a variable
$output = $proc.StandardOutput.ReadToEnd()
$output += $proc.StandardError.ReadToEnd()
# The ReadToEnd() makes everything 1 long string, so we break it up by carriage return, and filter
$output -split "`n"
# Write to log file for email capture
$output >> $myLogFile
"" | Tee-Object -Variable RoboLog
$RoboLog >> $myLogFile
#---------------------------------------------------------------------------------------------------
# GoodSync backup jobs are now complete.
#---------------------------------------------------------------------------------------------------