PowerShell v2 Gather remote software inventory


I was recently asked to gather information on every Adobe product installed on 576 Windows servers.

I thought this would be no problem, because I could use Get-WmiObject with the Win32_Product Class and go home early.

Alas, it was not to be: Per the WMI blog (http://blogs.msdn.com/wmi/default.aspx),

Windows Server 2003 doesn’t have the Win32_Product Class by default (http://blogs.msdn.com/wmi/archive/2009/09/16/wmi-remote-query-for-win32-product-class-results-in-generic-failure-error-0x80041001.aspx)

Well, that’s great. So, I cannot use Win32_Product.

Of course, I CAN read the registry key Uninstall, and parse the values.

For this, I used Shay Levi’s excellent Get-RegString from his “Stand Alone Registry Functions Library”  (http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2007/10/30/stand-alone-registry-functions-library.aspx)

I modified the function to use a $defaultValue of $null as I am specifically passing the value I want. Shay has $defaultValue set to “Your default value”

Note that I use the new in v2 method of creating custom objects on lines 43 – 48, 66 – 71, and 79 – 83, and a Try..Catch.

If I went with the old object creation, and used old style error catching, it could be done in v1 also.

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
026
027
028
029

030
031
032

033
034
035
036
037

038
039
040
041

042

043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060

061
062
063
064

065

066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087

function Get-RegString{ 
param( 
[string]$server = ".", 
[string]$hive, 
[string]$keyName, 
[string]$valueName, 
[object]$defaultValue = $null
) 
$hives = [enum]::getnames([Microsoft.Win32.RegistryHive]) 
if($hives -notcontains $hive){ 
write-error "Invalid hive value"; 
return; 
} 
$regHive = [Microsoft.Win32.RegistryHive]$hive; 
$regKey = `
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($regHive,$server); 
$subKey = $regKey.OpenSubKey($keyName); 
if(!$subKey){ 
write-error "The specified registry key does not exist."; 
return; 
} 
$subKey.GetValue($valueName,$defaultValue); 
} 
$AllServers = @()
$ServerObj  = @()
$Servers = Get-Content Servers.txt
foreach ($server in $Servers)
{
$i ++
Write-Progress `
-Activity "Gathering Adobe Data" `
-Status "Percent Completsd: " `
-PercentComplete (($i / $Servers.Count) * 100)
try
{
. Get-RegString $server "localMachine" `
"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" 
if ($subKey -ne $null)
{
foreach ($key in $SubKey.GetSubKeyNames())
{
$Publisher = Get-RegString $server "localMachine" `
"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$key" `
"Publisher" 
if ($Publisher -match "Adobe*")
{
#Found some adobe product so gather data
$Name = Get-RegString $server "localMachine" `
"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$key" `
"DisplayName"
$Version = Get-RegString `
$server "localMachine" `
"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$key" `
"DisplayVersion"
$hash = @{
Server = $server
Name = $Name
Version = $Version
}
$ServerObj = New-Object PSObject -Property $hash
$AllServers += $ServerObj
}
}
}
. Get-RegString $server "localMachine" `
"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
if ($subKey -ne $null)
{
foreach ($key in $SubKey.GetSubKeyNames())
{
$Publisher = `
Get-RegString $server "localMachine" `
"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$key" "Publisher"
if ($Publisher -match "Adobe*")
{
#Found some adobe product so gather data
$Name = Get-RegString $server "localMachine" `
"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$key" `
"DisplayName"
$Version = Get-RegString $server "localMachine" `
"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$key" `
"DisplayVersion"
$hash = @{
Server = $server
Name = $Name
Version = $Version
}
$ServerObj = New-Object PSObject -Property $hash
$AllServers += $ServerObj
}
}
}
}
catch
{
$hash = @{
Server = $server
Name = $Error[0].Exception.InnerException.Message.Trim()
}
$ServerObj = New-Object PSObject -Property $hash
$AllServers += $ServerObj
}
}
$AllServers |Export-Csv "Adobe.csv" -NoTypeInformation

Here is a sample of the output from the script:

001
002
003
004
005
006
007
008
009
Name,Server,Version
Adobe Reader 6.0,Server1,6
The network address is invalid.,Server2,
The network address is invalid.,Server3,
Requested registry access is not allowed.,Server4,
Adobe Reader 9.1.2,Server5,9.1.2
Spelling Dictionaries Support For Adobe Reader 9,Server5,9.0.0
Adobe Flash Player 10 ActiveX,Server6,10.0.32.18
Adobe Reader 9.2,Server6,9.2.0
Advertisement
  1. Remotely install ‘Win32_Product Class’ on Server 2003 « Unlock-PowerShell

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: