Powershell help -

TeeJayHoward

Limpness Supreme
Joined
Feb 8, 2005
Messages
12,271
I encountered an issue this morning where the bossman wanted to know which servers in our domain were running 32-bit versions of Windows Server. Thankfully, he was asking a different admin, but I decided to try and tackle it on my own as well. The objective was to find every machine on our domain with "Server" in the OS version, and then I'd need to look at those machines and find the 32-bit versions. Well, Get-ADComputer can return the OS Version, but it can't tell if the machine is 32-bit or not. Get-WMIObject Win32_Computer_Sytem can tell me if the machine is 32-bit or not, but it can't tell me if it's running Windows Server. So, I wrote up a quick powershell script that would execute two commands, and combine the outcome. Unfortunately, I seem to have hit a wall, and I'm not sure what's going on. To test out my scripts, I queried a block of computers which by name. Everything worked out great. I then tried to find computers based on OS Version instead of name. RPC failures everywhere. If I run the same command outside of the script, targeting a specific machine, it works great. This tells me that there's no firewall issues, etc. The command works... When not put in a script. What gives?

This code works:
Code:
$GetInfo = Get-ADComputer -Filter {Name -Like "*MachineName*"} -Properties * |
    ForEach-Object {
        $wmi = Get-WMIObject Win32_ComputerSystem -computer $_.Name
        New-Object PSObject -Property @{
            'Name'             = $_.Name
            'Operating System' = $_.OperatingSystem
            'Service Pack'     = $_.OperatingSystemServicePack
            'Architecture'     = $wmi.SystemType
	    'Manufacturer'     = $wmi.Manufacturer
	    'Model'	       = $wmi.Model
        }
    } | Format-Table Name,'Operating System','Service Pack',Architecture,Manufacturer,Model -Auto -Wrap
$GetInfo
This code, however:
Code:
$GetInfo = Get-ADComputer -Filter {OperatingSystem -Like "*Server*"} -Properties * |
    ForEach-Object {
        $wmi = Get-WMIObject Win32_ComputerSystem -computer $_.Name
        New-Object PSObject -Property @{
            'Name'             = $_.Name
            'Operating System' = $_.OperatingSystem
            'Service Pack'     = $_.OperatingSystemServicePack
            'Architecture'     = $wmi.SystemType
	    'Manufacturer'     = $wmi.Manufacturer
	    'Model'	       = $wmi.Model
        }
    } | Format-Table Name,'Operating System','Service Pack',Architecture,Manufacturer,Model -Auto -Wrap
$GetInfo

Just returns a bunch of RPC errors:
Code:
Get-WMIObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At C:\arch.ps1:3 char:16
+         $wmi = Get-WMIObject Win32_ComputerSystem -computer $_.Name
+                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
However, if I run the Get-WMIObject command and manually enter the server name, the results appear as desired:
Code:
PS C:\Windows\system32> Get-WMIObject Win32_ComputerSystem -computer HAL


Domain              : contoso.com
Manufacturer        : HP
Model               : ProLiant DL380 G6
Name                : HAL
PrimaryOwnerName    : Windows User
TotalPhysicalMemory : 25759043584
If I run the Get-ADComputer command, it returns a list of servers, just like I want:
Code:
PS C:\Windows\system32> Get-ADComputer -Filter {OperatingSystem -Like "*Server*"} |Format-Table Name

Name                                                                                                                      
----                                                                                                                      
HAL
<snip>

So all the individual pieces work out great. It's just when they're put together that they want to not play nice. Can someone find my goof for me?
 
Last edited:
Hmmm, not sure why yet, but it only breaks when you try to put it into the $GetInfo variable. Running without '$GetInfo =' it works just fine. Need to play with this some more to see what's going on here.
 
You know what, I think its because you're trying to connect to a computer that's powered off :)

You're just seeing the errors as its making the WMI connections. I'd imagine if you query every server in AD, some are bound to powered off, so you get the error. You can either sit through and let the script finish (it should return you're ouput eventually), or try wrapping it in a Try/Catch and for the catch run a Test-Connection -computername $_.name -count 1 and see if they respond to ping.

Hopefully that helps.
 
Code:
$GetInfo = Get-ADComputer -Filter {OperatingSystem -Like "*Server*"} -Properties * |
    ForEach-Object {
        try {$wmi = Get-WMIObject Win32_ComputerSystem -computer $_.Name}
        catch {write-host "Error" $_.Name; continue}
        }
 }
If you add in try/catch, you can have it spit out which machine is causing the error. I ran your original code here without error (but I only have one windows server in my VM lab). My first guess would be....you're hitting an AD account for a server that isn't powered up?

You could also run it in the Powershell ISE app. You can add add a breakpoint at the "new-object" like. When it breaks, you'll be able to use the console pane to manually run commands.

edit: Didn't see wilsonrdfl's response. I agree...
 
Actually, you may even wanna run something like this to skip the offline servers all together

<snip>
foreach {
Try {
Test-Connection -Count 1 -ComputerName $_.Name -ErrorAction Stop
$wmi = #the rest of your foreach loop from before
}
Catch {
Write-Host "Couldnt connect to $($_.Name)"
}
}
</snip>

That'll check to see if each computer is online first before trying to establish a WMI connection, so you don't have to wait for each WMI call to timeout.
 
Code:
$GetInfo = Get-ADComputer -Filter {OperatingSystem -Like "*Server*"} -Properties * |
    ForEach-Object {
        try {$wmi = Get-WMIObject Win32_ComputerSystem -computer $_.Name}
        catch {write-host "Error" $_.Name; continue}
        }
 }
If you add in try/catch, you can have it spit out which machine is causing the error. I ran your original code here without error (but I only have one windows server in my VM lab). My first guess would be....you're hitting an AD account for a server that isn't powered up?

You could also run it in the Powershell ISE app. You can add add a breakpoint at the "new-object" like. When it breaks, you'll be able to use the console pane to manually run commands.

Yeah, I have some powered down VM's in my lab and I get the same thing, gotta be what's causing the error.
 
Back
Top