I’m feeding an Invoke-Command a list of servers to run a script and return results. Everything works as I want, except for servers that it cannot connect to (obviously).
What I would like is to have the script also output a list of the computers that were unable to successfully connect with the Invoke-Command, so I know which ones were offline and not part of the results (instead of just seeing the default error messages).
The important part of the code currently looks something like this:
$Results = @()
$Results = invoke-command -computername ‘PC1’,‘PC2’,‘OfflinePC’,‘PC3’,‘PC4’
{get-service}
write-output $Results
donj
October 23, 2015, 7:19am
2
You probably need to do one computer at a time, so that when one fails, you know which one it was.
$computers = @('PC1','PC2','OfflinePC','PC3','PC4')
foreach ($computer in $computers) {
Try {
Invoke-Command -Script { get-service } -Computer $computer -ErrorAction Stop
} catch {
Write-Warning "$computer failed"
}
}
You don’t get parallelization that way, though. A different approach would be to use jobs.
invoke-command -computername 'PC1','PC2','OfflinePC','PC3','PC4' -AsJob
You’ll get a master job for the entire command, with sub-jobs that track each machine. You’ll be able to run Receive-Job to get the results, and easily see which ones failed.
IMHO, there’s no need to do an invoke command when using get-service.
try this, It will list the failed computer name in the error message.
$Servers = (‘localhost’,‘Server1’,‘Computer2’)
foreach($Server in $Servers){
$Output = Get-Service -ComputerName $Server | select machinename,status,name,displayname
$Output
}
The get-service command was just an example. I’m actually doing something more complicated in the invoke-command, but I didn’t want to confuse the question with that information.
I will try the AsJob code and see how that goes.
Thanks!
“The get-service command was just an example. I’m actually doing something more complicated in the invoke-command”
Please post, I’m interested in learning more about using the invoke-command.
Here’s the full script. I stole the heart of it from another script that did much more than I needed it to do. The thing I needed was just to see which computers were offline and which still had uninstalled updates, so I could tell that my scheduled install of server updates actually got them all installed and that nobody was still rebooting. I coded the ability to get the update data as the only output, but for my usual purposes it just displays that and then a list of offline computers and a list of computers needing updates.
Function Get-PendingWindowsUpdates
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1,ParameterSetName='List')]
[string[]]$ComputerName='localhost',
[Parameter(Mandatory=$False)]
[switch]$RawOutput
)
Begin {
Remove-Job 'MSPatch' -ErrorAction SilentlyContinue
Invoke-Command -ComputerName $ComputerName -AsJob -JobName MSPatch -ScriptBlock {
Write-Verbose "Start of script on $Computer"
#$VerbosePreference=$Using:VerbosePreference
$Computer = $env:COMPUTERNAME
$UpdateCollection = @()
Write-Verbose "Create Microsoft.Update.Session object for $Computer"
$objSession = [activator]::CreateInstance([type]::GetTypeFromProgID("Microsoft.Update.Session",$Computer))
Write-Verbose "Create Microsoft.Update.Session.Searcher object for $Computer"
$objSearcher = $objSession.CreateUpdateSearcher()
$objResults = $objSearcher.Search("IsInstalled = 0")
$PreFoundUpdatesToDownload = $objResults.Updates.count
Write-Verbose "Found [$PreFoundUpdatesToDownload] Updates in pre search criteria"
Foreach($Update in $objResults.Updates)
{
$Status = ""
If($Update.IsDownloaded) {$Status += "D"} else {$status += "-"}
If($Update.IsInstalled) {$Status += "I"} else {$status += "-"}
If($Update.IsMandatory) {$Status += "M"} else {$status += "-"}
If($Update.IsHidden) {$Status += "H"} else {$status += "-"}
If($Update.IsUninstallable) {$Status += "U"} else {$status += "-"}
If($Update.IsBeta) {$Status += "B"} else {$status += "-"}
Add-Member -InputObject $Update -MemberType NoteProperty -Name ComputerName -Value $Computer
Add-Member -InputObject $Update -MemberType NoteProperty -Name KB -Value $Update.KBArticleIDs
Add-Member -InputObject $Update -MemberType NoteProperty -Name Size -Value $Update.MaxDownloadSize
Add-Member -InputObject $Update -MemberType NoteProperty -Name Status -Value $Status
$Update.PSTypeNames.Clear()
$Update.PSTypeNames.Add('PSWindowsUpdate.WUList')
If ($Update.IsDownloaded) {$UpdateCollection += $Update}
} #End Foreach $Update in $objResults.Updates
$FoundUpdatesToDownload = $UpdateCollection.count
Write-Verbose "Found [$FoundUpdatesToDownload] Updates in post search criteria"
Return $UpdateCollection
} #End Invoke
Get-Job 'MSPatch' | Wait-Job
$JobList = Get-Job 'MSPatch' -IncludeChildJob
$ComputerFailed = @()
$ComputerHasPatch = @()
$UpdateAllList = @()
ForEach ($Job in $Joblist) {
If ($Job.name -like 'Job*') {
Write-Verbose $Job.Location
If ($Job.state -like "Failed") {
Write-Verbose "Computer is offline"
$ComputerFailed += $Job.Location
}
If ($Job.HasMoreData -eq $True) {
Write-Verbose "Computer has patches"
$ComputerHasPatch += $Job.Location
$UpdateAllList += Receive-Job $Job.Id
}
}
}
Remove-Job 'MSPatch' -ErrorAction SilentlyContinue
If ($RawOutput) {
Write-Output $UpdateAllList
} else {
$UpdateAllList | Sort-Object -Property Computername,KB | Format-Table -Property ComputerName,KB,Size,Status,Title -AutoSize
Write-Output "Computers with updates"
$ComputerHasPatch
Write-Output ""
Write-Output "Offline Computers"
$ComputerFailed
}
}
} #End Function Get-PendingWindowsUpdates