Pages

8/31/2012

Powershell: Server Software Inventory

Example of gathering software inventory from the registry. I used it to report on what version of Symantec products are installed on servers.

###################################################################
#
#  SAV-Inv.ps1
#
# Go through all Windows Server machine accounts in AD
# Report OS version from AD
# Look in registry Uninstall Key and report Symantec items
#
# Produce CSV output
#
###################################################################

$outfile = "Symantec-Inventory.csv"

if ( test-path $outfile ) { remove-item $outfile }

# Find AD machine accounts that are Windows Servers 
$strCategory = "computer" 
$strOS = "Windows*Server*"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry 
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher 
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("OperatingSystem=$strOS")
$colProplist = "OperatingSystem","dnshostname"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
$array = @()
$index = 0

# Look at each server
foreach ($objResult in $colResults) 
 { 
  $found=''
  $version=''
  $objComputer = $objResult.Properties;  
  $Server = [string]$objComputer.dnshostname
  $Server = $Server -replace "\s{2,}", ""
  $Server = $Server -replace "\.usa\.DOMAIN\.com", ""
  $OS = [string]$objComputer.operatingsystem
  $computername = $Server
  $computername
  "    $OS"
  $reg=''
  $regkey=''
  $subkeys=''
  $obj=''
  if (Test-Connection -ComputerName $Server -quiet -count 1) { #responds to PING
    #Define the variable to hold the location of Currently Installed Programs
    $UninstallKey="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" 
    #Create an instance of the Registry Object and open the HKLM base key
    $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computername)
 if (-not $reg) { #Failed to open registry
  $obj = New-Object PSObject
  $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
  $obj | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $OS
  $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayName" -Value "ERROR:  Cannot Access Remote Registry"
  $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayVersion" -Value "N/A"
  $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value "N/A"
  $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value "N/A"
  $array = $array + $obj
  "    ERR-Registry"
  continue
 }#registry fail
 #Drill down into the Uninstall key using the OpenSubKey Method
 $regkey=$reg.OpenSubKey($UninstallKey) 
 if (-not $regkey) { #Failed to open registry
  $obj = New-Object PSObject
  $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
  $obj | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $OS
  $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayName" -Value "ERROR:  Cannot Access Remote Registry"
  $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayVersion" -Value "N/A"
  $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value "N/A"
  $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value "N/A"
  $array = $array + $obj
  "    ERR-Registry"
  continue
  }#registry fail
 else {#registry success
  #Retrieve an array of strings that contain all the subkey names
  $subkeys=$regkey.GetSubKeyNames() 
  #Open each Subkey and use GetValue Method to return the required values for each
  foreach($key in $subkeys){
   $thisKey=$UninstallKey+"\\"+$key 
   $thisSubKey=$reg.OpenSubKey($thisKey) 
   $obj = New-Object PSObject
   $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
   $obj | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $OS
   $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayName" -Value $($thisSubKey.GetValue("DisplayName"))
   $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayVersion" -Value $($thisSubKey.GetValue("DisplayVersion"))
   $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value $($thisSubKey.GetValue("InstallLocation"))
   $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $($thisSubKey.GetValue("Publisher"))
   if ($obj.Publisher -match "Symantec") {
    $array = $array + $obj
    "    FOUND"
    $found = "1"
    }#if
   }#else   
  } #foreach key
  if (-not $found) { # No Symantec found
    $obj = New-Object PSObject
    $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
    $obj | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $OS
    $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayName" -Value "No Symantec Published Apps Installed"
    $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayVersion" -Value "N/A"
    $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value "N/A"
    $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value "N/A"
    $array = $array + $obj
    "    NOT FOUND"
 }#registry success
  }#if
  else {#no ping response
        $obj = New-Object PSObject
        $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
        $obj | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $OS
        $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayName" -Value "ERROR:  No PING response"
        $obj | Add-Member -MemberType NoteProperty -Name "AppDisplayVersion" -Value "N/A"
        $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value "N/A"
        $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value "N/A"
        $array = $array + $obj
        "    NO RESPONSE"
  }#else

}#foreach

$array | Where-Object { $_.AppDisplayName } | select ComputerName, OperatingSystem, AppDisplayName, AppDisplayVersion, Publisher | Export-CSV  $outfile -notype