Friday, January 8, 2010

Quickly Discover Domain Joined Computers Available via Ping

Occasionally, well…often, I need to run a series of commands or queries against a set of computers on our network.  Sometimes it doesn’t really matter to me to hit 100% of that set.  For instance, the other day I wanted to know roughly how many computer had login script timeout warnings in the event log for the past week.
In the past I had done something like:
  1. Get the list of computers I need to run against from Active Directory or a csv file.
  2. For each computer, attempt to ping it and if it responds run ye’ commands.
That works quickly enough when there are only 10-20 computers, but when we’re talking a scale of 500-1000+ computers it doesn’t scale so well.  Using Powershell, PSCX, Quest’s AD cmdlets, and the following code I can get the list of all domain joined computers currently available on our network in roughly 30 seconds:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
$adComputers = Get-QADComputer -SearchRoot 'domain.com/OU/OU' `
   -SizeLimit 0 `
   -IncludedProperties lastlogontimestamp | Where-Object `
   {
      (($_.useraccountcontrol -band 0x2) -eq 0) `
      -and ($_.lastlogontimestamp -ne $null) `
      -and (($_.lastlogontimestamp).adddays(30) -gt (Get-Date))
   }
$compNames = $adComputers | % { $_.name }
$pingResults = ping $compNames -Count 2 -Quiet `
               -AllAddresses -Asynchronous -ErrorAction silentlycontinue
$compDict = @{}
foreach ($comp in $adComputers)
{
   $compDict.add($comp.name,$comp)
}
$upComps = @()
foreach ($result in $pingResults)
{
   if ($result.received -gt 1)
   {
      $cName = $result.hostname -replace "\.domain\.com"
      $upComps += $compDict[$cName]
   }
}
Replace the ‘domain.com/OU/OU’ with the searchroot for the workstation groups you’re after, as well as the “\.domain\.com” with the correct information for your domain and $upComps will contain a collection of QADComputer objects that responded to pings.
From there we can use PSRemoting or tools like psexec.exe with the –d switch to (relatively) quickly run a set of commands against our computers that are up and running!
Many thanks to Lee Holmes for the script that creates the above code block on the clipboard for pasting from any script, truly awesome.