Utils/Get-InstalledSoftware.ps1
# ============================================================================= # Created on: 06/16/18 @ 11:21 # Created by: Alcha # Organization: HassleFree Solutions, LLC # Filename: Get-InstalledSoftware.ps1 # Notes: Adapted from the InstalledSoftware.ps1 script available here: # https://powershellgallery.com/packages/InstalledSoftware/2.0/DisplayScript # ============================================================================= <# .SYNOPSIS Gets a list of installed software for each computer name provided. .DESCRIPTION Analayzes the registry of each computer name provided for all of the installed software and returns it as an array. .PARAMETER Name The name(s) of the computers to get the list of installed software from. .EXAMPLE PS C:\> Get-InstalledSoftware Gets a list of all the currently installed software and returns it as an array. #> function Get-InstalledSoftware { [CmdletBinding()] param ( [Alias('Computer', 'ComputerName', 'HostName')] [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] [System.String[]] $Name = $env:COMPUTERNAME ) begin { $LMKeys = "Software\Microsoft\Windows\CurrentVersion\Uninstall", "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" $LMType = [Microsoft.Win32.RegistryHive]::LocalMachine $CUKeys = "Software\Microsoft\Windows\CurrentVersion\Uninstall" $CUType = [Microsoft.Win32.RegistryHive]::CurrentUser } process { foreach ($Computer in $Name) { $script:MasterKeys = @() if (!(Test-Connection -ComputerName $Computer -count 1 -quiet)) { Write-Error -Message "Unable to contact $Computer. Please verify its network connectivity and try again." -Category ObjectNotFound -TargetObject $Computer break } $CURegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($CUType, $Computer) $LMRegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($LMType, $Computer) Get-SubKeyObjects $LMKeys $LMRegKey Get-SubKeyObjects $CUKeys $CURegKey $script:MasterKeys = ($script:MasterKeys | Where-Object { ($null -ne $_.Name) -and ($_.SystemComponent -ne "1") -and ($null -eq $_.ParentKeyName) } | Select-Object ComputerName, Name, Version, UninstallCommand | Sort-Object Name) return $script:MasterKeys } } } <# .SYNOPSIS This is an internal/private function that is only used to simplify the flow of code within this script. Instead of having these foreach loops all within the original function, I placed them here and call this function. #> function Get-SubKeyObjects { param ( [Parameter(Mandatory = $true, Position = 0)] $BaseKey, [Parameter(Mandatory = $true, Position = 1)] [Microsoft.Win32.RegistryKey]$RegistryKey ) process { foreach ($Key in $BaseKey) { $RegKey = $RegistryKey.OpenSubkey($Key) if ($RegKey -ne $null) { foreach ($SubName in $RegKey.getsubkeynames()) { foreach ($Sub in $RegKey.opensubkey($SubName)) { $script:MasterKeys += (New-Object PSObject -Property @{ "ComputerName" = $Computer "Name" = $Sub.getvalue("displayname") "SystemComponent" = $Sub.getvalue("systemcomponent") "ParentKeyName" = $Sub.getvalue("parentkeyname") "Version" = $Sub.getvalue("DisplayVersion") "UninstallCommand" = $Sub.getvalue("UninstallString") "InstallDate" = $Sub.getvalue("InstallDate") }) } } } } } } #region HTML Code $Head = @" <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script> "@ $HeaderRow = @" <tr> <th>Name</th> <th>Version</th> <th>Uninstall Command</th> </tr>`n "@ $TopBody = @" <h1 class="text-center display-1">Installed Software</h1> <p class="text-center">This is a table of software installed on LINCLER as of <b>$(Get-Date -UFormat "%A, %B %d %Y @ %T")</b>.</p> "@ $Rows = "" #endregion HTML Code #region HTML Functions <# .SYNOPSIS This is an internal/private function that is only used to simplify the flow of code within this script. It returns the HTML code required to build a table using the provided $DataRows parameter. #> function Get-Table { param ( [Parameter(Position = 0)] [System.String] $DataRows ) return @" $TopBody <table id="SoftwareTable" class="table table-sm"> <thead> $HeaderRow </thead> <tbody> $DataRows </tbody> </table> "@ } <# .SYNOPSIS Gets a list of installed software for each computer name provided and puts it in an HTML file. .DESCRIPTION Analayzes the registry of each computer name provided for all of the installed software and then creates a decent looking table within an HTML file with all of the values. .PARAMETER Name The name(s) of the computers to get the list of installed software from. .EXAMPLE PS C:\> Get-InstalledSoftware Gets a list of all the currently installed software and returns it as an array. #> function Get-InstalledSoftwareAsHtml { [CmdletBinding()] param ( [Alias('Computer', 'ComputerName', 'HostName')] [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] [System.String[]] $Name = $env:COMPUTERNAME ) foreach ($Program in Get-InstalledSoftware -Name $Name) { $Name = $Program.Name $Version = $Program.Version $UninstallCmd = $Program.UninstallCommand if (Test-Path $UninstallCmd) { $Rows += @" <tr class="table-success"> <td>$Name</td> <td>$Version</td> <td style="font-style: italic;">$UninstallCmd</td> </tr>`n "@ } elseif ($UninstallCmd -match 'MsiExec.exe') { $Rows += @" <tr class="table-warning"> <td>$Name</td> <td>$Version</td> <td style="font-style: italic;">Start-Process -FilePath cmd.exe -ArgumentList '/c', '$UninstallCmd'</td> </tr>`n "@ } else { $Rows += @" <tr class="table-primary"> <td>$Name</td> <td>$Version</td> <td style="font-style: italic;">& $UninstallCmd</td> </tr>`n "@ } } $Body = Get-Table $Rows ConvertTo-Html -Body $Body -Head $Head -Title 'Installed Software' } #endregion HTML Functions |