Get-InstalledSoftware PowerShell Commandlet

This cmdlet will get the installed software that is contain in the HKLM set of keys from a local, remote or list of computers, and will return various information about the programs. It will return the name, current version and uninstall string . It pulls from the same locations that Add/Remove Programs pulls from. This cmdlet was taken from the URL listed below, but I added the uninstall member to it to aid for use in application installation scripts.

Updated 1/15/18. GIS 2.0. Supports pipeline data for software names. Supports get-help capabilities. Added cmdlet binding support, including verbose, debug, whatif and confirm support. Contains line by line commenting for explanation.

Function Get-InstalledSoftware{ 
<#

.SYNOPSIS
Gets installed software on local or remote computers. 

.DESCRIPTION
This Script will query the registry to get programs that are registered as installed on the machine
It will query both the 32bit registry and the 64bit registry. 
It queries HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
and HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
This script could be used to query for a piece of software and uninstall it using the Uninstall String property that is returned.
It also returns a version number, so it can be used to check if a piece of software is a certain version or not

.PARAMETER SoftwareName
Specify the name of the software that you wish to search for. The function uses wilcards so you do not need to have the exact name. Use quotation marks if there are multiple words in the software

.PARAMETER Computers
Specify the name of a computer, or a series of computers, to get software remotely from. This parameter is optional and if it is not specified, the local machine will be queried

.EXAMPLE
Get-InstalledSoftware -SoftwareName Office
Gets any software like the name Office on your local machine

.EXAMPLE
Get-InstalledSoftware -SoftwareName "Adobe Acrobat" -Computers COMPUTER1
Gets any software like the name Adobe Acrobat on a remote computer with the name COMPUTER1

.EXAMPLE
Get-InstalledSoftware -SoftwareName "Engagement" -Computers COMPUTER1,COMPUTER2
Gets any software like the name Engagement on two remote computers with the names COMPUTER1 and COMPUTER2

.LINK
    http://jongurgul.com/blog/installedsoftware/

.OUTPUTS
Selected.System.Management.Automation.PSCustomObject
    Returns a custom PSPbject or series of objects with the following properties: ComputerName, Software Name, Publisher, InstallDate, Estimated Size, Uninstall String, Version and if it is in the 64 bit registry location

.INPUTS
String, series of strings. You can pipe name of softwares to search for using this commandlet.

.NOTES
    Author:  Curtis Wright
    Email:   curtis (at) cwew.co 
    Date:    14JAN2018 
    PSVer:   2.0/3.0/4.0/5.0 

#>
#Allowing Cmdlet Bindings
[CmdletBinding(SupportsShouldProcess=$true)] 
#Defining Parameters   
    Param(
    [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$False)] 
  [Alias("SN","Software")]
  [String[]]$SoftwareName,
  [Parameter(Position=1,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$false)] 
  [Alias("CN","Computer")] 
    [String[]]$Computers = $ENV:ComputerName
    )
Begin{
#If the computer name is not supplied, use the local machine 
If (!$Computers) 
    {
    Write-Verbose "Using $ENV:ComputerName as the computer to search"
    $Computers = $ENV:ComputerName
    }
}
Process{
    #Build a PSObject to store the values that are obtained from the registry 
    Write-Debug "Builing PSObject as a template store individual software results in"
    $Base = New-Object PSObject; 
    $Base | Add-Member Noteproperty ComputerName -Value $Null; 
    $Base | Add-Member Noteproperty Name -Value $Null; 
    $Base | Add-Member Noteproperty Publisher -Value $Null; 
    $Base | Add-Member Noteproperty InstallDate -Value $Null; 
    $Base | Add-Member Noteproperty EstimatedSize -Value $Null;
    $Base | Add-Member Noteproperty UninstallString -Value $Null; 
    $Base | Add-Member Noteproperty Version -Value $Null; 
    $Base | Add-Member Noteproperty Wow6432Node -Value $Null;
    #Results is a generic list to store all results in 
    $Results =  New-Object System.Collections.Generic.List[System.Object]; 
    $NumberofComps = $Computers.Count
    Write-Verbose "Getting software for $NumberofComps computers, $Computers"
    ForEach ($ComputerName in $Computers){
    if ($PSCmdlet.ShouldProcess($ComputerName,"Getting software like $SoftwareName"))
    {
        Write-Verbose "Getting Software for $ComputerName"
        #Setting Remote Registry so that required information can be read
        Set-Service RemoteRegistry -ComputerName $ComputerName -StartupType Automatic | Out-Null 
        Set-Service RemoteRegistry -ComputerName $ComputerName -Status Running | Out-Null 
        #Resetting the resgitry value in case this being run for multiple computers
        $Registry = $Null; 
        #Trying to get the remote registry
        Try{
        Write-Debug "Trying registry for $ComputerName"
        $Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$ComputerName);
        } 
        Catch{Write-Error "$($_.Exception.Message)";} 
        #If the registry exists, get information 
        If ($Registry){
            #Resetting previous values 
            $UninstallKeys = $Null; 
            $SubKey = $Null;
            #Getting the subkeys values 
            $UninstallKeys = $Registry.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Uninstall",$False);
            #Foreach loop to get the values for each subkey in the subkey name arrary 
            $UninstallKeys.GetSubKeyNames()|%{ 
                $SubKey = $UninstallKeys.OpenSubKey($_,$False); 
                $DisplayName = $SubKey.GetValue("DisplayName");
                #Filtering out for display names less than 0 
                If ($DisplayName.Length -gt 0){ 
                    $Entry = $Base | Select-Object *
                    #Getting ComputerName 
                    $Entry.ComputerName = $ComputerName; 
                    #Getting DisplayName
                    $Entry.Name = $DisplayName.Trim();  
                    #Getting Publisher
                    $Entry.Publisher = $SubKey.GetValue("Publisher");
                    #Getting the the installed date  
                    [ref]$ParsedInstallDate = Get-Date 
                    If ([DateTime]::TryParseExact($SubKey.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){                     
                    $Entry.InstallDate = $ParsedInstallDate.Value 
                    }
                    #Getting the estimated size 
                    $Entry.EstimatedSize = [Math]::Round($SubKey.GetValue("EstimatedSize")/1KB,1);
                    #Getting Uninstall string
                    $Entry.UninstallString = $Subkey.GetValue("UninstallString");
                    #Getting the display version
                    $Entry.Version = $SubKey.GetValue("DisplayVersion");
                    #Adding software info to results list 
                    [Void]$Results.Add($Entry); 
                } 
            } 
             
                If ([IntPtr]::Size -eq 8){ 
                $UninstallKeysWow6432Node = $Null; 
                $SubKeyWow6432Node = $Null; 
                $UninstallKeysWow6432Node = $Registry.OpenSubKey("Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",$False); 
                    If ($UninstallKeysWow6432Node) { 
                        $UninstallKeysWow6432Node.GetSubKeyNames()|%{ 
                        $SubKeyWow6432Node = $UninstallKeysWow6432Node.OpenSubKey($_,$False); 
                        $DisplayName = $SubKeyWow6432Node.GetValue("DisplayName"); 
                        If ($DisplayName.Length -gt 0){ 
                            $Entry = $Base | Select-Object * 
                            $Entry.ComputerName = $ComputerName; 
                            $Entry.Name = $DisplayName.Trim();  
                            $Entry.Publisher = $SubKeyWow6432Node.GetValue("Publisher");  
                            [ref]$ParsedInstallDate = Get-Date 
                            If ([DateTime]::TryParseExact($SubKeyWow6432Node.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){                      
                            $Entry.InstallDate = $ParsedInstallDate.Value 
                            } 
                            $Entry.EstimatedSize = [Math]::Round($SubKeyWow6432Node.GetValue("EstimatedSize")/1KB,1);
                            $Entry.UninstallString = $Subkeywow6432Node.GetValue("UninstallString"); 
                            $Entry.Version = $SubKeyWow6432Node.GetValue("DisplayVersion"); 
                            $Entry.Wow6432Node = $True; 
                            [Void]$Results.Add($Entry); 
                            } 
                        } 
                    } 
                } 
        } 
    }
    
    }
    }
    End{
    #If no software name is supplied, return all results
    if (!$SoftwareName)
    {
    Write-Verbose "No Software detected as being searched for, returning all" 
    $Results 
    }
    else
    {
        #Return the results of the software names based on a wildcard 
        foreach ($name in $SoftwareName)
        {
            Write-Verbose "Returning Results for $name"
            $Results | ?{$_.name -like "*$Name*"}   
        }
    }
    
}
}
Set-Alias GIS Get-InstalledSoftware

Comments

Popular posts from this blog

SCCM PXE Boot Issues - No Advertisements Found

SCCM PXE Boot Issues - UEFI and Secure Boot

Outlook VBA Macros for Journal Entries