Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Get the List of installed softwares on remote computers with PowerShell

I used to use generally win32_product wmi class to fetch installed software list from remote computer systems. But the problem with it is, It only retrieves the installed applications via MSI, However, this WMI class might not list all the installed softwares that show in Add or Remove Programs, appwiz.cpl. One answer to this issue is to collect data on installed softwares/programs from the registry, (note that not all software inscribe to the registry when they are setup on the windows computer)" https://technet.microsoft.com/en-us/library/ee692772.aspx#EBAA WMI requests on class win32_product are repeatedly slow and can yield up to 1-3 minutes for each machine. It essentially runs every MSI to collect the software data information. This could be exploited very easily. In fact for examples, when you do this for certain Intel driver software you reset the default values. This may conflict with your security policy if they are predefined.

Another option is win32reg_addremoveprogams wmi class, but it comes only when you install SCCM client.

Installed software information is stored in registry under below paths.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

There is one more location, but in most of the cases no application or nothing will be listed there.
HKEY_USERS\User_SID\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

This script is based on my earlier articles and requires Remote Registry service up and running.

Part 1: Powershell: Get registry value data from remote computer
Part 1.1: Microsoft Powershell: Export remote registry information to excel
Part 2: Microsoft Powershell: remotely write, edit, modify new registry key and data value
Part 3: Microsoft Powershell: Delete registry key or values on remote computer

powershell remote registry get information of software remote applications remote softwares

Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Installing, importing and using any module in powershell

Download script here, This is also available on Github. To use this script copy paste in ps1 file and follow above blogs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#function Get-InstalledSoftwareInfo {
<#  
  .Synopsis  
    Get installed software information from remote computer.
  .Description  
    This cmdlet Get-InstalledSoftwareInfo will fetch and retrive information from remote and local computer. This requires remote registry service to be running. 
  .Example  
    Get-InstalledSoftwareInfo -ComputerName Server01
     
   This retrives list from computername server01
  .Example
    Get-InstalledSoftwareInfo -ComputerName Server01 | Export-CSV -Path c:\temp\info.csv
    Get-InstalledSoftwareInfo -ComputerName Server01 | ft

    Using pipeline information can be exported to CSV or shows tablewise
  .OutPuts  
    ComputerName DisplayName                                                    DisplayVersion Publisher             InstallDate EstimatedSize   
    ------------ -----------                                                    -------------- ---------             ----------- --------
    Server01     Microsoft Visual C++ 2012 x64 Additional Runtime - 11.0.61030  11.0.61030     Microsoft Corporation 20171225    5.82MB  
    Server01     Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161 9.0.30729.6161 Microsoft Corporation 20170820    1.04MB 
  .Notes  
    NAME: Get-InstalledSoftwareInfo
    AUTHOR: Kunal Udapi
    CREATIONDATE: 02 January 2018
    LASTEDIT: 7 January 2017  
    KEYWORDS: Get installed software application information
  .Link  
   #Check Online version: http://kunaludapi.blogspot.com
   #Check Online version: http://vcloud-lab.com
   #Requires -Version 3.0  
  #>
[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com')]
    Param ( 
        [parameter(Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
        [alias('C')]
        [String[]]$ComputerName = 'server01' #'.'
    )
    Begin {
    }
    Process {
        Foreach ($Computer in $ComputerName) {
            if (Test-Connection $Computer -Count 2 -Quiet) {
                $RegistryHive = 'LocalMachine'
                $RegistryKeyPath = $('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
                $RegistryRoot= "[{0}]::{1}" -f 'Microsoft.Win32.RegistryHive', $RegistryHive
                $RegistryHive = Invoke-Expression $RegistryRoot -ErrorAction Stop
                foreach ($regpath in $RegistryKeyPath) {
                    try {
                        $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryHive, $Computer)
                        $key = $reg.OpenSubKey($regpath, $true)
                    }
                    catch {
                        Write-Host "Check permissions on computer name $Computer, cannot connect registry" -BackgroundColor DarkRed
                        Continue
                    }
                    foreach ($subkey in $key.GetSubKeyNames()) {
                        $Childsubkey = $key.OpenSubKey($subkey)
                        $SoftwareInfo = $Childsubkey.GetValueNames()
                        $Displayname = $Childsubkey.GetValue('DisplayName')
                        [Int]$rawsize = $Childsubkey.GetValue('EstimatedSize')
                        $ConvertedSize = $rawsize / 1024
                        $SoftwareSize = "{0:N2}MB" -f $ConvertedSize
                        if ($SoftwareInfo -contains 'DisplayName') {
                            $SoftInfo = [PSCustomObject]@{
                                ComputerName = $Computer
                                DisplayName = $Childsubkey.GetValue('DisplayName')
                                DisplayVersion = $Childsubkey.GetValue('DisplayVersion')
                                Publisher = $Childsubkey.GetValue('Publisher')
                                InstallDate = $Childsubkey.GetValue('InstallDate')
                                EstimatedSize = $SoftwareSize
                                InstallLocation = $Childsubkey.GetValue('InstallLocation')
                                InstallSource = $Childsubkey.GetValue('InstallSource')
                                UninstallString = $Childsubkey.GetValue('UninstallString')
                                RegistryLocation = $Childsubkey.Name
                            }
                            $SoftInfo
                        }
                        $Childsubkey.close()
                    }
                $key.close()
                }
            }
            else {
                Write-Host "Computer Name $Computer not reachable" -BackgroundColor DarkRed
            }
        }
    }
    End {
        #[Microsoft.Win32.RegistryHive]::ClassesRoot
        #[Microsoft.Win32.RegistryHive]::CurrentUser
        #[Microsoft.Win32.RegistryHive]::LocalMachine
        #[Microsoft.Win32.RegistryHive]::Users
        #[Microsoft.Win32.RegistryHive]::CurrentConfig
    }
}
#Get-InstalledSoftwareInfo -ComputerName Server01, Member01 | ft

Although if you are using latest PowerShell version 5.x and there is no requirement to gather this information from remote registry, There is by default native command provided Get-Package. It can be easily used with Powershell remoting/ winrm to pull data. This will even get the patches, updates and hotfixes information.

POWERSHELL PS REMOTING BETWEEN STANDALONE WORKGROUP COMPUTERS 

microsoft windows powershell 5, desktop version, powershell core, Get-package, msu, msi and install application remotely

Useful Articles
GUI - SETUP AND CONFIGURE POWERSHELL WEB ACCESS SERVER (GATEWAY)
USE POWERSHELL ON MOBILE - SETUP AND CONFIGURE POWERSHELL WEB ACCESS (PSWA)
Powershell Trick : Execute or run any file as a script file
Set Powershell execution policy with Group Policy
Powershell execution policy setting is overridden by a policy defined at a more specific scope

Go Back



Comment

Blog Search

Page Views

12278813

Follow me on Blogarama