Patch/Cmdlets/Misc/Start-ProcessWithErrorHandling.ps1
<#
.SYNOPSIS Starts a process to handle commands, standard output, and standard error redirection. .DESCRIPTION Starts a process to handle commands, standard output, and standard error redirection. .PARAMETER FilePath Specifies the path to the executable. .PARAMETER ArgumentList Lists of arguments passed to the executable .PARAMETER TimeOut Specifies the timeout for the process. If the value is set to 0, the function waits for the process to end. #> function Start-ProcessWithErrorHandling { [CmdletBinding()] param ( [parameter(Mandatory=$true)] [string]$FilePath, [parameter(Mandatory=$true)] [string[]]$ArgumentList, [parameter(Mandatory=$false)] [int]$TimeOut = 0 ) Write-Verbose "Running external command: $FilePath $ArgumentList" $StdErrFile = [System.IO.Path]::GetTempFileName() $StdOutFile = [System.IO.Path]::GetTempFileName() $result = Start-Process -FilePath $FilePath -PassThru -NoNewWindow -RedirectStandardError $StdErrFile -RedirectStandardOutput $StdOutFile -ArgumentList $ArgumentList # progress indication, assume upper bound 500 sec # start the pogress indicator after 5 sec [int]$percent = 0; $program = Split-Path $FilePath -Leaf while ($result.WaitForExit(5000) -eq $false) { Write-Progress -Activity "Running $program..." -PercentComplete $percent -CurrentOperation "$percent% complete" -Status "Please wait." # naive algoritm stops progress indication at 95% if ($percent -lt 95) { $percent = $percent + 1; } if ($TimeOut -ne 0) { # Decrease timeout with wait cycles $TimeOut -= 5 if ($TimeOut -le 0) { Write-Error "Running $program timed out" $result | Stop-Process -ErrorAction SilentlyContinue break } } } Write-Progress -Activity "Running $program..." -PercentComplete 100 -CurrentOperation "100% complete" -Completed -Status "Done." $outputFromProcess = Get-Content $StdOutFile $errorOutputFromProcess = Get-Content $StdOutFile # Many exe files send the same content to stderr and stdout # if we have the same number of lines in the stderr and stdout, we will only write log the stderr # if the line numbers are different we will write both logs if (@($outputFromProcess).Count -ne @($errorOutputFromProcess).Count) { $outputFromProcess | ForEach-Object {Write-Verbose " $_"} # indent } $errorOutputFromProcess | ForEach-Object {Write-Verbose " $_"} # indent [int]$exitCode = $result.ExitCode if ($exitCode -ne 0) { [string] $output = $errorOutputFromProcess Write-Error "$FilePath $ArgumentList failed with error $exitCode`n$output" } } Export-ModuleMember -Function Start-ProcessWithErrorHandling |