Session open but Invoke-command fails with error

In my script I am opening connections to over 500 servers with:

$pso = New-PSSessionOption -IdleTimeout 1800000 -NoMachineProfile -MaxConnectionRetryCount 2 -OpenTimeout 30000 -SkipCACheck
$Ses = New-PSSession -ComputerName $Comp -SessionOption $pso -Credential $cred -Authentication Kerberos
[void]$PsSessions.Add($Ses)

Later I’m using invoke-command with:

$ReturnedResults = Invoke-Command -Session $PsSessions -FilePath .\Get-Details.ps1

The issue I’m having is that a chunk of servers cannot be reached despite the successful creation of a session to them. So, when the script gets to executing the invoke-command (around a hundred servers) error out with this:

Unable to contact the server. This may be because this server does not exist, it is currently down, or it does not
have the Active Directory Web Services running.
+ CategoryInfo : ResourceUnavailable: (SERVERNAME:ADComputer) [Get-ADComputer], ADServerDownException
+ FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
+ PSComputerName : SERVERNAME.FQN

I have debugged the script and paused it after the sessions are made to check if the sessions are valid and they list off as open with Get-PsSession.

I don’t understand why PS can make a session and have it open then not be able to connect to with Invoke-Command. What am I missing?

Have you tried pushing PsSessions through a ForEach and passing individual sessions into Invoke-Command?

something like

$ReturnedResults = @()

ForEach($PSSession in $PSSessions) {
    $ReturnedResults += Invoke-Command -Session $PSSession -FilePath .\Get-Details.ps1
}

Will need to store the results iteratively in an array

This is terrible advice.

First, the obvious, long known issue of arrays being fixed size. Depending on how many servers this could be extremely slow. If you must collect one at a time (this is not an instance) then use a System. Generic.Collections.List, see the example later on. For any type of loop like this, you can simply collect the output and let powershell handle populating the variable for you

$ReturnedResults = ForEach($PSSession in $PSSessions) {
    Invoke-Command -Session $PSSession -FilePath .\Get-Details.ps1
}

The next major issue with this advice is you will be running each of these consecutively. If there are many servers, this will take exponentially longer. I would recommend instead to gather any failures in an error variable for further processing/investigation like this.

$ReturnedResults = Invoke-Command -Session $PsSessions -FilePath .\Get-Details.ps1 -ErrorAction SilentlyContinue -ErrorVariable errorlist

Any failures won’t kill the entire execution and will be neatly stored in the $errorlist variable

For those times where there is a need to collect output one by one, here’s an example of using a list

ReturnedResults = New-Object System.Collections.Generic.List[object]

ForEach($PSSession in $PSSessions) {
    $current = Invoke-Command -Session $PSSession -FilePath .\Get-Details.ps1
    $ReturnedResults.Add($current)
}

or

ReturnedResults = New-Object System.Collections.Generic.List[object]

ForEach($PSSession in $PSSessions) {
    $ReturnedResults.Add((Invoke-Command -Session $PSSession -FilePath .\Get-Details.ps1))
}

Note the extra set of parenthesis needed around the command

1 Like

Perhaps it’s not clear, so here I’ll try to clarify.

Why can PowerShell connect to a server with new-pssession and then NOT be able to connect to it with invoke-command?

Are you 100% sure that none of the 500 servers has an issue hinted in the error message?

I’d try to reduce complexity first and start with smaller batches of computernames. Maybe only one at a time to make sure the code actually works as intended. :love_you_gesture:t3:

This would certainly explain the ability to connect but then fail the script.

Alright point taken. I was not going for efficiency, I was more advising in a troubleshooting sense. Just wanted to give him an easy way to submit a single session to the invoke-command cmdlet. You are correct that it is definitely not the most efficient.

I wish we could scrub the internet of the countless examples just like it. New users never know the hidden pitfalls and it doesn’t take long to get into the “why is powershell so stinking slow” situation that is inevitable. Either that or wish the powershell team would fix the issue behind the scenes which they could do easily but don’t due to “backwards compatibility concerns”

1 Like

Network issues, reboots, other temporary issue that occurs after the session was created. The default throttle limit on Invoke-Command is 32 so by the time one of these have their turn maybe there is something going on that would even prevent the session from being created at that point in time. If you’re going to run 32 max maybe you should break them up into chunks and create the sessions you are immediately going to call, rinse and repeat.

1 Like