How to check if a background job has timed out in powershell - powershell

I have this as part of a script
$timeoutSeconds = $timeoutMinutes * 60
$job = Start-Job -ScriptBlock $block -ArgumentList #($environment, $filter)
Wait-Job $job -Timeout $timeoutSeconds
Stop-Job $job
Remove-Job $job
And I would like to raise an error (is part of an octopus deploy step) if it's timed out
Thanks

How about something like this:
Wait-Job $job -Timeout $timeoutSeconds
if ($job.state -eq 'Running') {
Write-Error "Job timed out but did not complete."
}
$jobResults = Receive-Job $job
$jobResults
Stop-Job $job
Remove-Job $job

Related

Capture Verbose Stream from Job

I am trying to be a good a powerscript user and use Write-Verbose as per best practices, but I have no way to get the Verbose stream from a running Job.
$Job = Start-Job -Name "Scanning Work Item" -ScriptBlock{
Write-Verbose "Write-Verbose"
Write-Host "Write-Host"
}
while ($Job.HasMoreData -or $Job.State -eq "Running") {
Receive-Job -Job $Job -Verbose
Start-Sleep -Seconds 1
}
The output for this is
Write-Host
Please only answer with tested code as I have spent hours trying various permutations of Powershell script.
First of all, you're not getting any verbose ouput because you haven't changed the default VerbosePreference for the session.
As for reading Verbose ouput while the job is running, you can read each of the output stream buffers from the associated child job individually, without doing a Receive-job, and without affecting later output when you do the Receive-Job,
$Job = Start-Job -Name "Scanning Work Item" -ScriptBlock{
$VerbosePreference = 'Continue'
Write-Verbose "Write-Verbose"
Write-Host "Write-Host"
Start-Sleep -Seconds 10
}
Start-sleep -Seconds 2
$Verbose = $Job.ChildJobs[0].verbose.readall()
$verbose
while ($Job.HasMoreData -or $Job.State -eq "Running") {
Receive-Job -Job $Job
Start-Sleep -Seconds 1
}
Write-Verbose
VERBOSE: Write-Verbose
Write-Host

Wait for process to end

I have a powershell script that will automatically print all .pdf files in a folder with Foxit. I have it set to wait until Foxit has exited until the script continues. Every once in a while, the script will pause and wait even though Foxit has already exited. Is there a way to make it time out after a certain amount of time?
Here is the code I have:
Start-Process $foxit -ArgumentList $argument -Wait
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry
I've tried the recommendations here and they don't seem to work. For example if I do:
$proc = Start-Process $foxit -ArgumentList $argument
$proc.WaitForExit()
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry
I get:
You cannot call a method on a null-valued expression.
Any help would be greatly appreciated.
I think I figured it out. If I start it with Invoke-WmiMethod I can get the process ID and wait for it, then ask it to time out.
$proc = Invoke-WmiMethod -Class win32_process -Name create -ArgumentList "$foxit $argument"
Wait-Process -Id $proc.ProcessId -Timeout 120
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry
This seems to work pretty consistantly.
One way to implement a timeout is to use a background job:
$Job = start-job -ScriptBlock { write-output 'start';Start-Sleep -Seconds 15 }
$timeout = New-TimeSpan -Seconds 10
$timer = [diagnostics.stopwatch]::StartNew()
While ($timer.Elapsed -le $timeout)
{
if ($Job.State -eq 'Completed' )
{
Receive-Job $Job
Remove-Job $Job
Return
}
Start-Sleep -Seconds 1
}
write-warning 'Job timed out. Stopping job'
Stop-Job $Job
Receive-Job $Job
Remove-Job $Job
I ran into this same problem and found a slightly simpler solution that also captures the output of the child process. The -PassThru argument is key as it returns a process object for each process that the cmdlet starts.
$proc = Start-Process $foxit -ArgumentList $argument -PassThru
Wait-Process -Id $proc.Id -Timeout 120
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry
I prefer this style to have better control what to do during the runtime of the external process:
$waitTime = 60
$dism = Start-Process "$env:windir\system32\dism.exe" -ArgumentList "/Online /Cleanup-Image /ScanHealth" -PassThru -WindowStyle Hidden
while (!$dism.HasExited -or $waitTime -gt 0) {sleep -Seconds 1; $waitTime--}
"done."
By cheking the HasExited-attribute I can continue with my code with any other tasks in parallel.

start-job to run script parallelly

Please help , really very much worried
How to transform the below script using start-job , I have 6 Modules to compare , but sequentially it's taking too much time I am trying to adopt start-job option so that I can run this compare parallelly or in background
Tried this -
Start-Job -Name "Comparecontrol" -filepath $ExecuteSbtWithDcmDm -ArgumentList $CompareControl,"",$false,$false | Out-Null
echolog $THISSCRIPT $DCM_UPDATE_LOG_FILE $LLINFO "Finished Control Master Comparison
Main Script
The general flow would be something like this:
$jobs = #()
$jobs += Start-Job -scriptblock {...}
...
$jobs += Start-Job -scriptblock {...}
Wait-Job $jobs
$results = Receive-Job $jobs
You can use a job name as an alternative to storing the job instance returned by Start-Job e.g.:
$jobName = 'CompareControl'
foreach ($script in $scripts)
{
Start-Job -Name $jobName-scriptblock {&$script} -ArgumentList ...
}
Wait-Job -Name $jobName
$results = Receive-Job -Name $jobName

PowerShell Receive-Job does not work in script

When I execute $job = Start-Job { dir } an then Receive-Job $job in PowerShell console I get normal output. But when I make similar .ps1 script and run it there is no output. Other commands work correctly. How do I receive job result in scripts?
Just try wait job is completed before receive.
$job = Start-Job { dir }
Wait-Job $job | out-null
receive-job $job
other way
$job = Start-Job { dir }
while ($job.state -ne "Completed") {}
receive-job $job
You need to wait for the job to finish:
Start-Job { dir } | Wait-Job | Receive-Job

powershells' stuck jobs

I'm trying to make jobs with powershell but they get stuck for a reason.
Untitled2.ps1:
$A = "papa"
$B = "mama"
Start-Job -ScriptBlock { MainHA $args[0] $args[1] } -ArgumentList #($A, $B) -InitializationScript { . "C:\Tools\Untitled3.ps1" }
While (Get-Job -State "Running")
{
write-host Still working...
Get-Job | Receive-Job
Start-Sleep 1
}
Get-Job | Receive-Job
Remove-Job *
Untitled3.ps1:
Function MainHA ($x, $y)
{
write-host $x, $y
}
Any idea?
Are there any other jobs running?
One way to wait for the specific job you are starting is to store the job you start in a variable.
$job = Start-Job -ScriptBlock { MainHA $args[0] $args[1] } -ArgumentList #($A, $B) -InitializationScript { . "C:\Tools\Untitled3.ps1" }
While ($job.State -eq "Running") {
write-host Still working...
Receive-Job $job
Start-Sleep 1
}
Receive-Job $job
Remove-Job $job