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