zynory
zynory

Reputation: 53

PowerShell Invoke-Command timeout if no answer from frozen AD-Server

I'm writing a PowerShell-Script that reads all shares from all AD-Servers and outputs them into a csv-file. At the same time the script is saving all occuring errors and outputs them into an error-log. The script will be run as a weekly task. When I run the script, all goes well until it gets to a server that has frozen. In that case, the script will just run forever because it gets no answer from the server.

Now I need to add some sort of timeout that skips a server after it doesn't recieve an answer for a specific amount of time. How would I do that with my existing code?

My Code:


$computers = (Get-Content C:\PowerShell\Shares\serverlist.txt).ForEach({
    if(-not [string]::IsNullOrWhiteSpace($_))
    {
        "$_.domain.com"
    }
})

$remoteCode = {
    Get-SmbShare | Where-Object Path | Get-Acl |
    Select-Object -Property "PSChildName", "Path", "Group", "AccessToString"
}

$results = Invoke-Command -ComputerName $computers -ScriptBlock $remoteCode 2>&1
$errors, $good = $results.Where({$_ -is [System.Management.Automation.ErrorRecord]}, 'Split')

$good | Sort-Object PSComputerName | Select-Object "PSComputerName", "PSChildName", "Path", "Group", @{ Name = "AccessToString"; Expression = { $_.AccessToString -replace("268435456", "FullControl") -replace("-1610612736", "ReadAndExecute")}} | export-csv -path C:\PowerShell\Shares\shares.csv -NoTypeInformation -delimiter ";"

$errors.Exception.Message | Set-Content $error_logfile -Encoding Unicode

Upvotes: 4

Views: 1765

Answers (1)

Santiago Squarzon
Santiago Squarzon

Reputation: 60145

NOTE: This answer is pretty much useless, in an ideal world, -OperationTimeout would do what it's name implies, however, as the helpful comment from mklement0 states:

Unfortunately, the OperationTimeout session option doesn't do what its name suggests: see GitHub issue #15696. Implementing an actual operation-duration timeout is the subject of GitHub proposal #5434, which suggest adding a -Timeout parameter to Invoke-Command.

If you feel this would be a great implementation for future versions of PowerShell, consider up-voting his proposal!


You could use PSSessionOption with a Operation Timeout and Open Timeout below the default values (3 minutes):

See the Parameter section of New-PSSessionOption documentation:

-OpenTimeout
Determines how long the client computer waits for the session connection to be established. When the interval expires, the command to establish the connection fails.

-OperationTimeout
Determines the maximum time WinRM waits for positive connection tests from a live connection before initiating a connection time-out.

$timeOut = 30000 # => 30 seconds
$psso = New-PSSessionOption -OpenTimeout $timeOut -OperationTimeout $timeOut

$session = (Get-Content C:\PowerShell\Shares\serverlist.txt).ForEach({
    if(-not [string]::IsNullOrWhiteSpace($_)) {
        try {
            New-PSSession -ComputerName "$_.domain.com" -SessionOption $psso
        }
        catch {
            Write-Warning $_.Exception.Message
        }
    }
})

Then the rest of the script is the same, except for the use of -Session instead -ComputerName for Invoke-Command:

$results = Invoke-Command -Session $session -ScriptBlock $remoteCode 2>&1

And lastly, after you're done with the remote connections, you would need to remove the PSSessions:

Remove-PSSession $session

Upvotes: 4

Related Questions