Get-RemoteProgram Get list of installed programs on remote or local computer

This script generates a list by querying the registry and returning the installed programs of a local or remote computer. It allows for retrieval of additional properties such as the uninstall string of an application as well.

4.4 Star
104,761 times
Add to favorites
Operating System
E-mail Twitter Digg Facebook
Sign in to ask a question

  • How to run multiple instances
    2 Posts | Last post July 02, 2015
    • I will be running through a list of a few hundred servers and was wondering how I could run multiple instances of this while grabbing from the same list of servers?
    • There are a couple of ways of doing this and they are not unique to this script, I would advise using PowerShell jobs or runspaces if you would like to parallelize your workload.
      For example you could do this using PowerShell Jobs:
      1..5 | ForEach-Object {Add-Content -Path C:\Temp\Computers.txt -Value "Computer$_"}
      $SomeData = 'This is some data'
      foreach ($Computer in (Get-Content -Path C:\Temp\Computers.txt)) {
          Start-Job -Name $Computer -ScriptBlock {
                      Test="Test successfully run on $Using:Computer"
      Get-Job | Wait-Job | Receive-Job
      Alternatively you could use PowerShell RunSpaces, Boe Prox wrote a nice module for this:
      1..5 | ForEach-Object {Add-Content -Path C:\Temp\Computers.txt -Value "Computer$_"}
      $SomeData = 'This is some data'
      foreach ($Computer in (Get-Content -Path C:\Temp\Computers.txt)) {
          Start-RSJob -Name {$Computer} -ScriptBlock {
                      Test="Test successfully run on $Using:Computer"
      Get-RSJob | Wait-RSJob | Receive-RSJob
  • Separate list for installed program, update and hidden
    7 Posts | Last post April 23, 2015
    • Great utility. It seems to list three kind of entries:
      - Installed programs as found in the Control Panel for "Uninstall a program".
      - Installed updates as found in the Control Panel for "View installed updates".
      - Hidden installs that are in neither of the above two lists.
      It could be nice to allow generation of those three lists separately. It may be possible to identify the "Installed updates" and "Hidden installs" by the presence of the registry value IsMinorUpgrade and SystemComponent respectively, but I haven't been able to confirm that.
      Thank you in advance.
    • Actually I does not list all installed updates, only the updates that are stored in the ...\Windows\CurrentVersion\Uninstall\ path of the registry. For example updates for Microsoft Office, a method of exporting only the updates for example can currently be done by using the script in combination with Where-Object for example:
      Get-RemoteProgram -Property IsMinorUpgrade | Where-Object {[string]$_.IsMinorUpgrade}
    • The hidden installs are a different thing though, can you give me an example of a program or update that you would consider to be a 'Hidden' install?
    • Thanks for the sample command to extract the installed updates. Combined with Sort-Object, I should be able to get lists that more closely match the lists in the installed programs and installed updates control panels.
      For example of hidden installs, most of the one I found are part of the install of a larger product such as Visual Studio 2012 or Office 2013. The output of Get-RemoteProgram lists things like "Blend for Visual Studio 2012" and other "Blend for Visual Studio ...", "Dotfuscator and Analytics Community Edition" and more. They were installed by the Visual Studio 2012 installer. They are not listed in the lists for installed programs or installed updates control panels. Same for things like "Microsoft Access MUI (English) 2013", "Microsoft Excel MUI (English) 2013" that I'm pretty sure were installed by the Office 2013 installer.
    • Interesting, I am getting similar results in regards to the Office suite. I guess this is the difference between looking at the registry and using the proper providers which would filter out entries like these. As my intention for this script was to get the most relevant information possible, I will keep this information in the script.
      Thank you for getting back to me on that and if there's anything you would like added to the script let me know and I can see if I can work it into the script.
    • I agree. There is no need to change anything to your script. Using Where-Object and Sort-Object, I was able to split the output of your script into one list that pretty much matches what is in Installed Programs, a list that matches some groups in Installed Updates, and the remaining list that could be better called Installed Components instead of Hidden Updates:
      $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
      . $scriptPath\Get-RemoteProgram.ps1
      $nl = [Environment]::NewLine
      Write-Output "******************************${nl}${nl}${nl}Installed programs:${nl}${nl}${nl}******************************${nl}"
      Get-RemoteProgram -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent | Where-Object {[string]$_.SystemComponent -ne 1 -and ![string]$_.IsMinorUpgrade -and ![string]$_.ReleaseType -and ![string]$_.ParentDisplayName} | Sort-Object ProgramName
      Write-Output "******************************${nl}${nl}${nl}Installed updates:${nl}${nl}${nl}******************************${nl}"
      Get-RemoteProgram -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent | Where-Object {[string]$_.SystemComponent -ne 1 -and ([string]$_.IsMinorUpgrade -or [string]$_.ReleaseType -or [string]$_.ParentDisplayName)} | Sort-Object ParentDisplayName,ProgramName
      Write-Output "******************************${nl}${nl}${nl}Installed Components:${nl}${nl}${nl}******************************${nl}"
      Get-RemoteProgram -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent | Where-Object {[string]$_.SystemComponent -eq 1} | Sort-Object ProgramName
    • Very cool, thanks for posting the code here. I have updated the description of the script and put your code in there in case it is useful for someone else and gave you credits for it. Thanks Georges and I am happy to hear you are enjoying the script.
      Have a great day!
  • No output
    2 Posts | Last post April 10, 2015
    • Hi! I'm using your script but it's nothing outputs. No warnings or errors. OS is Win2008 (x64). What to do?
    • How are you currently running the script, are you using any parameters? Could you post the exact code you execute the script?
      Also make sure the function contained in the script is properly loaded, try executing the script as such:
      . .\Get-RemoteProgram.ps1;Get-RemoteProgram
  • Error:
    2 Posts | Last post March 14, 2015
    • I'm getting the following error: running from a 64 bit win 7 PC, any ideas?
      Works fine locally.
      PS C:\users\MyProfile\downloads> Get-RemoteProgram -ComputerName computer1
      Exception calling "OpenRemoteBaseKey" with "2" argument(s): "The network path was not found.
      At C:\users\MyProfile\downloads\Get-RemoteProgram.ps1:73 char:13
      +             $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microso ...
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
          + FullyQualifiedErrorId : IOException
      Thank you in advance.
    • The error message seems to indicate that there is a connectivity issue between the systems. Are you sure the other system is actually online, can you ping the machine? If the machine is verified to be online make sure that the firewall rules between the two systems allow remote registry access. Additionally assure that the following services are running:
      - Computer Browser
      - Remote Procedure Call
      - TCP/IP NetBIOS Helper Service
      - Remote Registry Service
      - Server
      - Workstation
  • Error
    3 Posts | Last post February 28, 2015
    • Jaap: I get this error. Also anyways to filter for specific app instead of all apps. Thx.
      You cannot call a method on a null-valued expression.
      At C:\scripts\Get-RemoteProgram.ps1:76 char:21
      +                     $RegBase.OpenSubKey($CurrentReg).GetSubKeyNames() |
      +                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull
    • I have 32bit PC, so removed 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' from registry location variable to solve.
      For filter:
      $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition 
      $inputFile = $scriptPath + "\get-RemoteProgram.txt"
      $Servers = Get-Content $inputFile
      Get-RemoteProgram -ComputerName $Servers -Property DisplayVersion | Where-Object {$_.ProgramName -like '*binkiland*'}
    • That is indeed not intended behavior, before releasing version 1.2 I did must have missed this error on 32-bit systems. I have updated the script to version 1.2.1, as manually having to edit the script was never my intention. I have added your name in the patch notes, thanks for letting me know the error was there vsk2014!
  • Not showing all "tools/apps" installed & how to uninstall?
    2 Posts | Last post February 22, 2015
    • Hey Jaap, 
      I am a big fan of your site and contributions all over the scripting world! I'm trying to use this script to gather the installed apps on hundreds of servers. 
      I'm testing on a few to start of course. I'm not seeing some "tools" that are installed on the systems that are the items I have to remove.  These tools are things like HP stuff that was put on some systems, some IBM stuff to collect logs, things like logmein, etc. I don't see the results coming back when I query systems I know have these items. Also I am sure the msi files for some of the items are gone from the servers, and others were .exe installs.  How can I remove these items remotely and can I leverage your script?
    • First of all I just updated the script after seeing your query, so try your luck with version 1.2 which filters out some errors when a registry base is not found.
      This script queries the registry for installed programs. A simple check on a system could be to check the Installed Programs on the server to verify the program is actually listed there as well. Could you give me an example of a tool that does not show up correctly, then I could try to reproduce the error.
      As for remotely uninstalling you can use this script for gathering the uninstallstrings for the programs you would like to uninstall. Then you could use these string to either schedule a remote uninstall by remotely creating a scheduled task on the machine or directly executing the task using either PowerShell remoting, psexec or another solution to remotely execute the uninstallstring on the system.
  • Nothing happens
    3 Posts | Last post August 03, 2014
    • Running the script from C:\Windows\System32 on a Windows 7 64-bit machine (named 1621L03).
      The full command I use is
      PS C:\Windows\system32> C:\windows\system32\Get-RemoteProgram.ps1 -ComputerName
      I get the warning about running untrusted scripts and choose to Run Once.
      Nothing happens. I'm returned to the PS C:\Windows\system32 prompt
    • Ensure you are running powershell as an administrator.  Right click on Powershell or Powershell ISE and select "Run as administrator".  If that doesn't work, go ahead and try adding the following lines to the script:
      $Computers = Read-Host 'What computer would you like the programs for (Comma delimited)?'
      Get-RemoteProgram -ComputerName  $Computers.Split(',')
      At this point, it should prompt you for the computer names you'd like to query.  Enter them in the format of - Server1,Server2,etc...
    • This might either be caused by the Execution-Policy or the fact that this is a file downloaded from the internet.
      Depending on which version of PowerShell you are using, you are able to remove the 'Downloaded from the internet' flag from this file by running the following:
      Unblock-File -Path Get-RemoteProgram.ps1
  • not working
    2 Posts | Last post August 03, 2014
    • I'm having the same issue as JMurphy70.  GlacierWaterIT, where you add the additional line within the script to make it work?
    • This might either be caused by the Execution-Policy or the fact that this is a file downloaded from the internet.
      Depending on which version of PowerShell you are using, you are able to remove the 'Downloaded from the internet' flag from this file by running the following:
      Unblock-File -Path Get-RemoteProgram.ps1
  • original script doesnt work
    2 Posts | Last post August 03, 2014
    • This was written more complicated than it needed to be, so I changed it. feel free to use it. Save it as get-remoteprogram.ps1
      get-remoteprogram computername
      $Computer = $args[0]
      		if (!$computer) {$computer = "This Computer"}
              $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer)
              $RegUninstall = $RegBase.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall')
              $RegUninstall.GetSubKeyNames() | 
              ForEach-Object {
                  $DisplayName = ($RegBase.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$_")).GetValue('DisplayName')
                  if ($DisplayName) {
                      New-Object -TypeName PSCustomObject -Property @{
                          ComputerName = $Computer
                          ProgramName = $DisplayName
    • Indeed, by removing the function block you are able to use the script directly instead of using the function. If you would like to use this function as a script instead removing the first and the last line of the script is all that it requires.
  • Script fetches wrong results from 32 bit servers targetting 64 bit servers.
    2 Posts | Last post August 03, 2014
    • Hi Jaap
      This method seems to have issues when you run it from a 32 bit server 2008/windwos 7 PS on 64 servers.
      Using WMI to query StdRegProv class is much faster too and yields consistent results, regardless of wat OS architecture its run from.
      Gopinath T
    • I see what you mean, I just updated the script with some additional functionality. I am considering adding in support for querying remote registry using wmi as well as .NET in a future release, but I will have to properly test this solution before I can implement this.
61 - 70 of 73 Items