0

I have a script which is fetching the disk space information of many machines in a call center. However, sometimes this function takes too long. I need to create a time out for that function and have been unable to. I tried using start-job but to be honest, I don't fully understand it and so I am not getting the desired results.

try {
    $timeoutSeconds = 30
    $code = {
      param($currentPCname, $activeDriveTypes)
// Function which takes computer name as input and outputs the ComputerName,DeviceID, Size, Freespace and DriveType (3 = local)
      function get-FDS { 
        [cmdLetBinding()]
        Param([string]$hostName)
        Get-WmiObject Win32_LogicalDisk -ComputerName $hostName | 
        Where-object {$_.DriveType -in $activeDriveTypes} | 
        select-Object @{Name="ComputerName";Expression={$hostName}}, @{Name="Date";Expression={Get-Date}}, DeviceID, Size, Freespace, DriveType
      } 
      get-FDS($currentPCname) -errorAction stop
    }
    $processTime = measure-command { 
      $j = Start-Job -ScriptBlock $code -Arg $currentPCname, $activeDriveTypes 
      if (Wait-Job $j -Timeout $timeoutSeconds) { $tempData = Receive-Job $j }
      $jobState = $j.state
      Remove-Job -force $j
    }
    if ($jobState -ne 'Completed') {
        $pcTurnedOn = $false
        $errorMessage = "ERROR talking to $currentPCname : Query timed-out"
        $query = "CALL sp_fds_insert_log(" + $currentRunID + ", '" + $errorMessage + "', '" + $scriptName + "');"
        $cmd = new-object mysql.data.mysqlclient.mysqlcommand($query, $conn) 
        $cmd.executenonquery()
    }
} catch {
    $pcTurnedOn = $false
    $errorMessage = "ERROR talking to $currentPCname : $_"
    $query = "CALL sp_fds_insert_log(" + $currentRunID + ", '" + $errorMessage + "', '" + $scriptName + "');"
    $cmd = new-object mysql.data.mysqlclient.mysqlcommand($query, $conn) 
    $cmd.executenonquery() 
}

The main point of the code above is that if the line below which is calling the $code segment

$processTime = measure-command { 
  $j = Start-Job -ScriptBlock $code -Arg $currentPCname, $activeDriveTypes
  if (Wait-Job $j -Timeout $timeoutSeconds) { $tempData = Receive-Job $j }
  $jobState = $j.state
  Remove-Job -force $j
}

takes more than 30 seconds which is the $timeoutSeconds, the last IF statement would be called, if the line above does not work for some reason, the catch statement would be called and if it works in less than 30 seconds, nothing would be called.

3
  • Start-Job returns a job object immediately, so when you do Measure-Command {$j = Start-Job ...} it's never going to take more than a few milliseconds Commented Jul 26, 2019 at 14:43
  • I understand, however, the problem is not the $processTime result as that can be easily fixed, what I am having a hard time with is letting the job run for maximum 30 seconds and then killing it. @MathiasR.Jessen Commented Jul 26, 2019 at 14:46
  • I've fixed that part, any ideas for the timeout buddy? @MathiasR.Jessen Commented Jul 26, 2019 at 14:55

1 Answer 1

3

If the job finished before the timeout is reached, Wait-Job will return the job itself - if the timeout is exceeded it won't return anything:

$timeout = 2
$job = Start-Job { Start-Sleep -Seconds 3 }
$done = $job |Wait-Job -TimeOut $timeout
if($done){
    # It returned within the timeout 
}
else {
    # Nothing was returned, job timed out
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you buddy very helpful :)
@EnriqueMingyarTorrezHinojos Thanks. I'm afraid I don't understand your question :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.