What am I missing? Script keeps looping

import-module Activedirectory $Servers = $null $ErrorActionPreference = "SilentlyContinue"

$Servers = Get-ADComputer -Filter ‘name -like “_”’ -SearchBase “OU=,OU=,OU=,OU=,DC=,DC=,DC=,DC=” -SearchScope Subtree -Properties Name | Sort Name

foreach ($objItem in $Servers) {
$Server = $objItem.Name
Write-Host “Checking uptime on servers…”

Get-WmiObject -ComputerName $Servers.name -ClassName win32_operatingsystem | select csname, @{LABEL=‘LastBootUpTime’;EXPRESSION={$.ConverttoDateTime($.lastbootuptime)}}
}

I have no issues with it running.

Ah, Hungarian notation. Brings back memories of my youth.

First, the $ErrorActionPreference you’re doing is an Incredibly Poor Idea. There’s also zero need to make $Servers null at the top. I’d strongly urge deleting those two lines - this isn’t VBScript :).

How many objects are in $Servers?

Your main error is that you’ve lost track of your variables. In Get-WmiObject, you’re passing “$Servers.name” as the computer name. That’s going to query EVERY SINGLE ONE OF THE SERVERS, and it will do that once for however many objects are in $Servers. So if you have 100 servers, it’s going to do it 100x100 times. 10,000 times. It’s not looping forever - just give it a few years to finish ;).

You probably meant to just use “$Server” instead, since you’ve taken the trouble of pulling $objItem.Name into $Server already.

Ugh, that really sucks. When I use just $servers, I get that the RPC server unavailable.

When I did $servers.name without ErrorAction, it gave me RPC server unavailable on a few servers, even if I did a test-connection. Back to the drawing board I guess… 'cause it’s probably a firewall issue blocking (I’m guessing).

Nope, you missed my point - use $server, singular, not $servers. Or, use “-ComputerName $objItem.Name” if you prefer. See where you defined $server to be the same as $objItem.Name?

$servers has many objects. You don’t want to use that. You’re enumerating it in a ForEach loop.

And RPC will be unavailable for anything running 2012R2 or later by default - MS has moved away from WMI and prefers Get-CimInstance now, which can speak both RPC and WS-MAN. And yeah, it could also be a firewall. But WMI is deprecated and on the way out - CIM rules, now. Test-Connection is a ping - it doesn’t test for RPC connectivity or availability.

The proper way to handle that error is described in our free ebook, “The Big Book of PowerShell Error Handling.”

I think, this is what Don meant:

import-module Activedirectory
$Servers = $null
$ErrorActionPreference = "SilentlyContinue"

$Servers = Get-ADComputer -Filter 'name -like "*_*"' -SearchBase "OU=,OU=,OU=,OU=,DC=,DC=,DC=,DC=" -SearchScope Subtree -Properties Name | Sort Name

#You might wanna take this link out of the ForEach as well
Write-Host "Checking uptime on servers..."

foreach ($objItem in $Servers) {
$Server = $objItem.Name

#Your line:
#Get-WmiObject -ComputerName $Servers.name -ClassName win32_operatingsystem | select csname, @{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}

#Recommeded line:
Get-CimInstance -ComputerName $Server -ClassName win32_operatingsystem | select csname, @{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}
} 

If you use Get-CimInstance the date is automatically converted to human format - don’t need the conversion just:

Get-CimInstance -ComputerName $Server -ClassName win32_operatingsystem | select csname, lastbootuptime

Ah, with your help and Leandro it worked! I’m going to have to read on Get-CimInstance vs Get-WMIObject and when/where each are applicable. Thanks.