public/Get-Software.ps1

Function Get-Software {
    <#
    .SYNOPSIS
    Get the installed software for local or remote machines
 
    .DESCRIPTION
    Get the installed software for local or remote machines.
    Requires the RemoteRegistry to be enabled on the machine.
    Will look for both x86 and x64 installed paths.
 
    .PARAMETER ComputerName
    Provide the computername(s) to query
    Default value is the local machine
 
    .EXAMPLE
    Get-SecurityUpdate -ComputerName 'CONTOSO-SRV01','CONTOSO-WEB01'
 
    Description
    -----------
    Gets the software information for both CONTOSO-SRV01 and CONTOSO-WEB01
 
    .NOTES
    Name: Get-Software.ps1
    Author: Robert Prüst
    Module: PSP-Inventory
    DateCreated: 21-02-2019
    DateModified: 01-03-2019
    Blog: http://powershellpr0mpt.com
 
    .LINK
    http://powershellpr0mpt.com
    #>


    [OutputType('PSP.Inventory.Software')]
    [Cmdletbinding()] 
    Param( 
        [Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] 
        [String[]]$ComputerName = $env:COMPUTERNAME
    )         
    Begin {
        $InventoryDate = Get-Date -f 'dd-MM-yyyy HH:mm:ss'
    }
    Process {     
        foreach ($Computer in $Computername) {
            $Computer = $Computer.ToUpper()
            if (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {
                $Paths = @("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "SOFTWARE\\Wow6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall")         
                foreach ($Path in $Paths) { 
                    Write-Verbose "Checking Path: $Path"
                    try { 
                        $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer, 'Registry64')
                    }
                    catch { 
                        Write-Error $_ 
                        Continue 
                    } 
                    try {
                        $regkey = $reg.OpenSubKey($Path)  
                        $subkeys = $regkey.GetSubKeyNames()      
                        foreach ($key in $subkeys) {   
                            Write-Verbose "Key: $Key"
                            $thisKey = $Path + "\\" + $key 
                            try {  
                                $thisSubKey = $reg.OpenSubKey($thisKey)   
                                $DisplayName = $thisSubKey.getValue("DisplayName")
                                if ($DisplayName -AND $DisplayName -notmatch '^Update for|rollup|^Security Update|^Service Pack|^HotFix') {
                                    $Date = $thisSubKey.GetValue('InstallDate')
                                    if ($Date) {
                                        try {
                                            $Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null)
                                        }
                                        catch {
                                            Write-Warning "$($Computer): $_ <$($Date)>"
                                            $Date = $Null
                                        }
                                    } 
                                    $Publisher = try {
                                        $thisSubKey.GetValue('Publisher').Trim()
                                    } 
                                    catch {
                                        $thisSubKey.GetValue('Publisher')
                                    }
                                    $Version = try {
                                        #Some weirdness with trailing [char]0 on some strings
                                        $thisSubKey.GetValue('DisplayVersion').TrimEnd(([char[]](32, 0)))
                                    } 
                                    catch {
                                        $thisSubKey.GetValue('DisplayVersion')
                                    }
                                    $UninstallString = try {
                                        $thisSubKey.GetValue('UninstallString').Trim()
                                    } 
                                    catch {
                                        $thisSubKey.GetValue('UninstallString')
                                    }
                                    $InstallLocation = try {
                                        $thisSubKey.GetValue('InstallLocation').Trim()
                                    } 
                                    catch {
                                        $thisSubKey.GetValue('InstallLocation')
                                    }
                                    $InstallSource = try {
                                        $thisSubKey.GetValue('InstallSource').Trim()
                                    } 
                                    catch {
                                        $thisSubKey.GetValue('InstallSource')
                                    }
                                    $HelpLink = try {
                                        $thisSubKey.GetValue('HelpLink').Trim()
                                    } 
                                    catch {
                                        $thisSubKey.GetValue('HelpLink')
                                    }
                                    $Software = [PSCustomObject]@{
                                        ComputerName    = $Computer
                                        DisplayName     = $DisplayName
                                        Version         = $Version
                                        InstallDate     = $Date
                                        Publisher       = $Publisher
                                        UninstallString = $UninstallString
                                        InstallLocation = $InstallLocation
                                        InstallSource   = $InstallSource
                                        HelpLink        = $thisSubKey.GetValue('HelpLink')
                                        EstimatedSizeMB = [decimal]([math]::Round(($thisSubKey.GetValue('EstimatedSize') * 1024) / 1MB, 2))
                                        InventoryDate   = $InventoryDate
                                    }
                                    $Software.PSTypeNames.Insert(0, 'PSP.Inventory.Software')
                                    $Software
                                }
                            }
                            catch {
                                Write-Warning "$Key : $_"
                            }   
                        }
                    }
                    catch {}   
                    $reg.Close() 
                }                  
            }
            else {
                Write-Error "$($Computer): unable to reach remote system!"
            }
        } 
    } 
}