Idera nSoftware Compellent

Run WMI query on every computer in an array of OUs


posted by tao.yang
06-24-2009

Downloads: 276
File size: 4.7kB
Views: 2,632

Embed
Run WMI query on every computer in an array of OUs
  1. #requires -version 2 
  2. param
  3. [string] $class = $(throw "The WMI Class is required."), 
  4. [array] $attributes
  5. [string] $NameSpace 
  6. $erroractionpreference = "SilentlyContinue" 
  7. $thisScript = Split-Path $myInvocation.MyCommand.Path -Leaf 
  8. $scriptRoot = Split-Path(Resolve-Path $myInvocation.MyCommand.Path
  9. $OutPutCSVFile = Join-Path $scriptRoot "WMIInventory.csv" 
  10.  
  11. #Default WMI Name Space is "Root\CIMV2" 
  12. if ($NameSpace -eq $null) {$NameSpace = "Root\CIMV2"
  13.  
  14. function CheckComputerConnectivity($computer
  15.     $result = $false 
  16.     #check if the computer can be pinged. 
  17.     "checking $computer" 
  18.     $ping = New-Object Net.NetworkInformation.Ping 
  19.     $PingResult = $ping.send($computer
  20.     if ($PingResult.Status.Tostring().ToLower() -eq "success"
  21.     
  22.         $result = $true                     
  23.     } else
  24.         Write-Host "$computer cannot be reached" 
  25.     
  26.     return $result 
  27.  
  28. function GetServersFromOU([string]$strDomainName, [array]$arrOUs, [array]$arrExcludedOus
  29.     $arrDCs = $strDomainName.split("."
  30.     $strFullDC = $null 
  31.     foreach ($DC in $arrDCs
  32.     
  33.         if ($strFullDC -eq $null
  34.         
  35.             $strFullDC = "DC=$DC" 
  36.         
  37.         else 
  38.         
  39.             $strFullDC = "$strFullDC,DC=$DC" 
  40.         
  41.     
  42.     #Get the Distingushed Names for Excluded OUs 
  43.     if ($arrExcludedOus -ne $null
  44.     
  45.         for ($i=0; $i -le ($arrExcludedOus.count-1); $i++
  46.         
  47.             $arrExcludedOus[$i] = $arrExcludedOus[$i] + ",$strFullDC" 
  48.         
  49.          
  50.     
  51.  
  52.     $arrComputers = @( ) 
  53.     foreach ($Ou in $arrOUs
  54.     
  55.         $strFilter = "computer" 
  56.                                          
  57.         $objDomain = New-Object System.DirectoryServices.DirectoryEntry 
  58.                                          
  59.         $objSearcher = New-Object System.DirectoryServices.DirectorySearcher 
  60.         $objSearcher.SearchRoot = "LDAP://$OU,$strFullDC" 
  61.         $objSearcher.SearchScope = "subtree"  
  62.         $objSearcher.PageSize = 3000 
  63.                                          
  64.         $objSearcher.Filter = "(objectCategory=$strFilter)" 
  65.         $colResults = $objSearcher.FindAll() 
  66.                      
  67.                          
  68.         foreach ($item in $colResults
  69.         
  70.             $objComputer = $item.GetDirectoryEntry() 
  71.             #Only add the computer to the array if it is not in the excluded OUs. 
  72.             $bCorrectOU = $true 
  73.             foreach ($Ou in $arrExcludedOus
  74.             
  75.                 if ($objComputer.distinguishedName.tostring() -match $Ou
  76.                 
  77.                     $bCorrectOU = $false 
  78.                     #Write-Host "$bCorrectOU, $objComputer.distinguishedName.tostring()" 
  79.                 
  80.             
  81.             if ($bCorrectOU -eq $true
  82.             
  83.                 $arrComputers += $objComputer.Name 
  84.             
  85.         
  86.     
  87.         $arrcomputers = $arrcomputers | Sort-Object 
  88.     return $arrComputers 
  89.  
  90. $strDomain = "<Domain>" 
  91. $arrOUs = @( ) 
  92. $ExcludedOus = @() 
  93. #adding OUs 
  94. $arrOus += "OU=<OU1>" 
  95. $arrOus += "OU=<OU2>,OU=<OU3>" 
  96. #Adding excluded OUs 
  97. $ExcludedOus += "OU=<OU4>,OU=<OU1>" 
  98. $ExcludedOus += "OU=<OU5>,OU=<OU1>" 
  99.  
  100. #Get computers 
  101. $arrComputers = GetServersFromOU $strDomain $arrOUs $ExcludedOus 
  102.  
  103.  
  104. $arrWMI = @() 
  105.  
  106. #if no desired attributes is passed in, use 'select *' when querying WMI class. 
  107. if ($attributes.count -eq 0 -or $attributes -eq $null
  108.     $attributes += "*" 
  109.     $strQuery = "Select" 
  110.     Foreach ($attribute in $attributes
  111.     
  112.         $strQuery = $strQuery + " $attribute," 
  113.     
  114.     $strQuery = $strQuery.substring(0, ($strQuery.length-1)) 
  115.     $strQuery = "$strQuery from $class" 
  116. Write-Host $strQuery 
  117.  
  118. foreach ($computer in $arrComputers
  119.         #Check connectivities 
  120.         $IsComputerAccessible = CheckComputerConnectivity $computer 
  121.         if ($IsComputerAccessible -eq $true
  122.         
  123.             #Get-WmiObject cannot be used because cannot set timeout for WMI queries 
  124.             Write-Host "Checking $computer..." 
  125.             $wmi = [WMISearcher]'' 
  126.             $wmi.options.timeout = '0:0:30'    #set timeout to 30 seconds 
  127.             $wmi.scope.path = "\\$Computer\$NameSpace" 
  128.             $wmi.query = $strQuery 
  129.             $ColObjWMI = $wmi.get() 
  130.              
  131.             #a collection is returned from above command 
  132.             Foreach ($obj in $ColObjWMI
  133.             
  134.                 #Create a custom psobject to only store the properties we need (including the computer name and WMI Class) 
  135.                 $psobjWMI = $null 
  136.                 $psobjWMI= New-Object psobject 
  137.                 Add-Member -InputObject $psobjWMI -membertype noteproperty -name ComputerName -value $computer 
  138.                 Add-Member -InputObject $psobjWMI -membertype noteproperty -name WMIClass -value $class 
  139.                  
  140.                 #Looping through each property and add to the custom psobject 
  141.                 Foreach ($property in ($Obj| Get-Member -MemberType Property)) 
  142.                 
  143.                     $strProperty = $property.Name 
  144.                     if ($strProperty.substring(0,1) -ne "_"
  145.                     
  146.                         $strValue = $obj.$strProperty 
  147.                         Add-Member -InputObject $psobjWMI -membertype noteproperty -name $strProperty -value $strValue 
  148.                     }     
  149.                 
  150.                 #Adding the custom psobject to an array 
  151.                 $arrWMI += $psobjWMI 
  152.             
  153.              
  154.         } else
  155.             $strError = "$Computer cannot be reached." 
  156.         
  157.  
  158. #Export the output array to CSV 
  159. $arrWMI | Select-Object -Property * -ExcludeProperty "_*"| Sort-Object | Export-Csv -notypeinformation $OutPutCSVFile -Force 

This script allows you to specify a WMI class and any properties that you wish to query, run the WMI query against every computer in an array of OUs (also allow you to exclude any child OUs that you do not wish to query). the Output is stored in a CSV file located on the same directory of the script.

The OUs and excluded OUs are hardcoded in the script and the WMI class, properties (optional) and WMI namespace (optional) are passed into the script as parameters. if no wmi class properties are specified, the scripts returns all properties from the class. if no namespace is specified, the default name space of "root\cimv2" is used.

Here are some sample commands to run the script:

.\WMIQuery.PS1 win32_service name, status

.\WMIQuery.PS1 Win32_OperatingSystem

.\WMIQuery.PS1 DELL_Chassis assettag root\cimv2\dell

Unfortunately this script has to run under an account that has admin rights to all the machines (e.g. a domain admin account). because it uses [wmisearcher] accelerator rather than get-wmiobject cmdlet (which allows you to use an alternative credential). I had to use [wmisearcher] because get-wmiobject does not allow you to set a timeout for the WMI queries. - Please let me know if you know how to overcome this problem.

Copyright 2010 PowerShell.com. All rights reserved.