I am trying to add software inventory to my XenApp V4 scripts. I do have it
working but to me it is not a generic solution that can grow and still be
manageable.
Here is close to the final version. This works with remote registry and
produces a list of unique installed apps. On my 6.5 server, I have duplicate
entries in both regkeys for MS SQL Server and Office.
There HAS to be a better way to do the exclusions. It would be nice to have a
list in the code BUT also allow someone to create a file of exclusions so the
list can be personalized per environment. What if someone has an application
silo that requires a specific version of Java. The current list would exclude
all Java stuff. What if someone needs to know what Java stuff is installed?
Here is my final list of software from my lab XenApp 6.5 server with 284 items
in the full list of installed software:
DisplayName
-----------
Adobe Reader XI (11.0.05)
Microsoft Office File Validation Add-In
Microsoft Office Professional Plus 2007
Microsoft Save as PDF Add-in for 2007 Microsoft Office programs
Microsoft SQL Server 2008
Microsoft SQL Server 2008 Native Client
Notepad++
Parallels Tools
And the testing code:
$InstalledApps = @()
$servers = Get-XAServer -EA 0 | sort-object FolderPath, ServerName
#Define the variable to hold the location of Currently Installed Programs
$UninstallKey1="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
$UninstallKey2="SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
ForEach($Server in $Servers)
{
#Create an instance of the Registry Object and open the HKLM base key
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Server.ServerName)
#Drill down into the Uninstall key using the OpenSubKey Method
$regkey1=$reg.OpenSubKey($UninstallKey1)
$regkey2=$reg.OpenSubKey($UninstallKey2)
#Retrieve an array of string that contain all the subkey names
$subkeys1=$regkey1.GetSubKeyNames()
$subkeys2=$regkey2.GetSubKeyNames()
#Open each Subkey and use GetValue Method to return the required values
for each
foreach($key in $subkeys1)
{
$thisKey=$UninstallKey1+"\\"+$key
$thisSubKey=$reg.OpenSubKey($thisKey)
If(![String]::IsNullOrEmpty($($thisSubKey.GetValue("DisplayName"))))
{
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name
"DisplayName" -Value $($thisSubKey.GetValue("DisplayName"))
$InstalledApps += $obj
}
}
foreach($key in $subkeys2)
{
$thisKey=$UninstallKey2+"\\"+$key
$thisSubKey=$reg.OpenSubKey($thisKey)
If(![String]::IsNullOrEmpty($($thisSubKey.GetValue("DisplayName"))))
{
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name
"DisplayName" -Value $($thisSubKey.GetValue("DisplayName"))
$InstalledApps += $obj
}
}
$JustApps = $InstalledApps |
Where-Object {$_.DisplayName -notlike "*32-bit Components*"} |
Where-Object {$_.DisplayName -notlike "*64-bit Components*"} |
Where-Object {$_.DisplayName -notlike "*(English)*"} |
Where-Object {$_.DisplayName -notlike "*(French)*"} |
Where-Object {$_.DisplayName -notlike "*(Spanish)*"} |
Where-Object {$_.DisplayName -notlike "*AnswerWorks*"} |
Where-Object {$_.DisplayName -notlike "*Customer Experience
Improvement*"} |
Where-Object {$_.DisplayName -notlike "*Interoperability Assemblies*"} |
Where-Object {$_.DisplayName -notlike "*Service Pack*"} |
Where-Object {$_.DisplayName -notlike "AppSense*"} |
Where-Object {$_.DisplayName -notlike "Apple*"} |
Where-Object {$_.DisplayName -notlike "Citrix*"} |
Where-Object {$_.DisplayName -notlike "Definition Update*"} |
Where-Object {$_.DisplayName -notlike "Hotfix*"} |
Where-Object {$_.DisplayName -notlike "Intel*"} |
Where-Object {$_.DisplayName -notlike "Java*"} |
Where-Object {$_.DisplayName -notlike "Machine Management WMI
Provider*"} |
Where-Object {$_.DisplayName -notlike "Machine Identity Service Agent*"}
|
Where-Object {$_.DisplayName -notlike "Microsoft .NET*"} |
Where-Object {$_.DisplayName -notlike "Microsoft Application
Virtualization*"} |
Where-Object {$_.DisplayName -notlike "Microsoft Office Access MUI*"} |
Where-Object {$_.DisplayName -notlike "Microsoft Silverlight*"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server 20??
Browser"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server 20?? Common
Files"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server 20??
Database Engine Services"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server 20??
Database Engine Shared"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server 20?? RsFx
Driver"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server 20?? Setup
*"} |
Where-Object {$_.DisplayName -notlike "Microsoft SQL Server VSS Writer"}
|
Where-Object {$_.DisplayName -notlike "Microsoft Visual C++*"} |
Where-Object {$_.DisplayName -notlike "MSXML*"} |
Where-Object {$_.DisplayName -notlike "NVIDIA*"} |
Where-Object {$_.DisplayName -notlike "Realtek*"} |
Where-Object {$_.DisplayName -notlike "Runtime*"} |
Where-Object {$_.DisplayName -notlike "Security Update*"} |
Where-Object {$_.DisplayName -notlike "Update*"} |
Where-Object {$_.DisplayName -notlike "User Profile Hive Cleanup
Service"} |
Where-Object {$_.DisplayName -notlike "VdaMonitorPlugin*"} |
Where-Object {$_.DisplayName -notlike "VMWare*"} |
Where-Object {$_.DisplayName -notlike "XenApp*"} |
Select-Object DisplayName | Sort DisplayName -unique
$JustApps
}
This DOES work and actually runs very fast. But this is not a manageable way
to manage exclusions.
Any clues, hints or solutions you want to send my way would be greatly
appreciated.
Thanks
Webster
================================================
Did you know you can also post and find answers on PowerShell in the forums?
http://www.myitforum.com/forums/default.asp?catApp=1