Works for Domain, why not Forest

I have this handy script to check patch status for a specific kb at the domain level

$DCs = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() |
        Select-Object -ExpandProperty DomainControllers |
            Select-Object -ExpandProperty Name

###Get kb status all DCs ###
Foreach ($DC in $DCS){		
    Invoke-Command -ComputerName $DC {
        Get-HotFix -Id KB5013941 -ComputerName $using:DC    
    }
}

but when I attempt at the Forest level (as Ent Admin):

# $DCs = foreach ($domain in (get-adforest -Identity forest.root).domains) { get-addomaincontroller -filter * -server $domain | select hostname}

Foreach ($DC in $DCS){		
    Invoke-Command -ComputerName $DC {
        Get-HotFix -Id KB5013941 -ComputerName $using:DC    
    }
}

I get error:

Invoke-Command : One or more computer names are not valid.

Actually you don’t need a loop. Invoke-Command can take an array of computer names. :wink:

Regardless of that … since $DCs is still an array of objects and not strings you should use $DCs.Name to specifically access the name property of the object.

1 Like
Invoke-Command -ComputerName $DCs.name Get-HotFix -Id KB5015736

got rid of the foreach but still see error

The simplest method is to verify the DCs just by printing them to check it once.

If you’re running Invoke-Command against a remote computer, then you DO NOT specify -ComputerName on the cmdlet being run remotely. You’re basically remoting to a system and trying to connect remotely to another system (even if it’s the same system.) Always remember if it has a -ComputerName parameter, that is generally indicating a remote connection.

Also, don’t slow the code down exponentially by looping a command that can take an array of targets.

$DClist = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() |
    Select-Object -ExpandProperty DomainControllers |
        Select-Object -ExpandProperty Name

$output = Invoke-Command -ComputerName $DClist -ScriptBlock {
    Get-HotFix -Id KB5013941 
} -ErrorAction SilentlyContinue -ErrorVariable errs

# do stuff with $output
$output

This is how I typically run it and then inspect $errs for any failures. Keep in mind, the way you’re currently outputting the Get-Hotfix command, nothing will be returned if the specified KB is not found. If you want to ensure an object is always returned, you can use something like this.

$DClist = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() |
        Select-Object -ExpandProperty DomainControllers |
            Select-Object -ExpandProperty Name

$output = Invoke-Command -ComputerName $DClist -ScriptBlock {
    $hotfix = Get-HotFix -Id KB5013941

    [PSCustomObject]@{
        ComputerName = $env:computername
        KB5013941    = [bool]$hotfix
    }
} -ErrorAction SilentlyContinue -ErrorVariable errs

“printing them to check it once”
not sure what that means, kv

if the error says one ore more computer names are invalid, that means one or more items in the $DCS variable is invalid, just for debugging execute the same foreach and print the name before invoke-command .

Foreach($DC in $DCS){
Write-Output "Current DC is [$DC]" 
# invoke-command
}

above print message will show the computer name in [], look for any special char or space.

1 Like