Wednesday, September 5, 2012

PowerShell: Get Report of Installed Applications Using Remoting

Below is a PowerShell script that uses PowerShell Remoting to pull a list of installed applications on a Windows system. Since the list is kept in the registry, you can easily use the Get-ChildItem cmdlet to take care of business. Found some resource links that helped me remove the Windows updates and hotfixes from the report.

##############################################################
# Script Name: PS_Remoting_Installed_Applications.ps1
# Version: 1.0
# Description: Using PowerShell Remoting Queries Remote
#               Systems for Installed Software
##############################################################

$allComputers = Invoke-Command -computername SERVER01,SERVER02,SERVER03 `
-scriptblock {  
                #Arrays for Holding Installed App Data 
                $installedApps = @();
                $installedAppsKeys = @();
                
                #Pull 32bit Installed Apps
                Get-ChildItem hklm:\Software\Microsoft\Windows\CurrentVersion\Uninstall `
                    | ForEach-Object { $installedAppsKeys += Get-ItemProperty $_.pspath `
                    | Where-Object {$_.DisplayName -and !$_.ReleaseType -and `
                    !$_.ParentKeyName -and ($_.UninstallString -or $_.NoRemove)} };
                #Check for 64bit Installed Apps and Pull Information
                if(Test-Path hklm:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall)
                {
                  Get-ChildItem hklm:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall `
                  | ForEach-Object { $installedAppsKeys += Get-ItemProperty $_.pspath `
                  | Where-Object {$_.DisplayName -and !$_.ReleaseType -and !$_.ParentKeyName `
                  -and ($_.UninstallString -or $_.NoRemove)} };
                }
                #Loop Through Installed Application Registry Keys and Pull Info
                foreach($instlApp in $installedAppsKeys)
                {
                    #Local Variables Used in Reporting
                    [string]$displayName = "";
                    [string]$displayVersion = "";
                    
                    #Check for DisplayName is Null or Emtpy
                    if(![string]::IsNullOrEmpty($instlApp.DisplayName))
                    {
                        $displayName = $instlApp.DisplayName.ToString();
                        #Check to See If Display Version is Null or Empty
                        if(![string]::IsNullOrEmpty($instlApp.DisplayVersion))
                        {
                           $displayVersion = $instlApp.DisplayVersion.ToString();
                        }
                        #Create Custom PSObject and Add to Reporting Array
                        $app = New-Object PSObject;
                        $app | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $displayName;
                        $app | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $displayVersion;
                        $installedApps += $app;
                    }
                 }
                #Send Back Reporting Array Sorted by Display Name
                $installedApps | Sort-Object DisplayName;                                                  
            }

$allComputers | Format-Table PSComputerName,DisplayName,DisplayVersion -AutoSize

PowerShell: WMI to Report Installed Applications on Remote Systems

Recently, I've been working with more PowerShell Remoting. Earlier this week I wrote a script that queries a list of systems for installed applications using Remoting. Tomorrow, I'm demo'ing that script (which I will post after this one) and needed to show how you would do it using just WMI in PowerShell. Since the listing of installed applications is stored in the Registery it took a good amount of time trying to figure out how to access a remote registry via PowerShell just using WMI. Below is the comparison script. Enjoy.


#########################################################
# Script Name: PS_Remote_WMI_Installed_Applications.ps1
# Version: 1.0
# Description: Using WMI Remotely Queries
#               Systems for Installed Software
#########################################################

#Array for Reporting Installed Software
$installedApps = @();

#Array for Registry Paths to Installed Apps
$appRegPaths = @("Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
                 "Software\Microsoft\Windows\CurrentVersion\Uninstall");

#Array of System Names to Run Against
$computers = @("SERVER01","SERVER02","SERVER03");

foreach($computer in $computers)
{
    #Ping System First
    if(Test-Connection -ComputerName $computer -Quiet)
    {
        #Connect to WMI Registry Class
        $uReg = [wmiclass]"\\$computer\root\default:StdRegProv";
                          
        foreach($regPath in $appRegPaths)
        {
            #Pull the Application Registry Keys 
            $iAppKeys = $uReg.EnumKey(2147483650,$regPath);
    
            #Null Check on Application Registry Keys
            if($iAppKeys)
            {
                #Loop Through Each Application Key
                foreach($appKey in $iAppKeys.sNames)
                {
                    #Construct Key Path
                    $keyPath = $regPath + "\" + $appKey.ToString();
                    
                    #Pull the Key DisplayName String Value
                    $keyDisplayName = $uReg.GetStringValue(2147483650,$keyPath,"DisplayName");
                    if(![string]::IsNullOrEmpty($keyDisplayName.sValue))
                    {
                        #Local Vars Used for Reporting
                        [string]$displayName = $keyDisplayName.sValue.ToString();
                        [string]$displayVersion = "";
                    
                        #Pull the Key DisplayVersion String Value
                        $keyDisplayVersion = $uReg.GetStringValue(2147483650,$keyPath,"DisplayVersion");
                        if(![string]::IsNullOrEmpty($keyDisplayVersion.sValue))
                        {
                            $displayVersion = $keyDisplayVersion.sValue.ToString();
                        }
                
                        #Create Custom PSObject and Add to Reporting Array
                        $app = New-Object PSObject;
                        $app | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computer;
                        $app | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $displayName;
                        $app | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $displayVersion;
                          $installedApps += $app;
                        
                    }#End of Null\Empty Check on DisplayName String Value
                    
                }#End of Foreach $iAppKeys
            
            }#End of Null Check on $iAppKeys
        
        }#End of Foreach Reg Path
    
    }#End of Test-Connection

}#End of Foreach Computer

$installedApps | Sort-Object ComputerName,DisplayName | Format-Table -AutoSize;