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
103,194 times
Add to favorites
Operating System
E-mail Twitter Digg Facebook
Sign in to ask a question

  • Weird, Get-RemoteProgram does not work
    2 Posts | Last post November 11, 2015
    • I've updated the help files but can't find Get-RemoteProgram because I am thrown the error that it is not a cmdlet, function, or operable program. Why? I have Powershell 4.0
    • Can you navigate to the folder in which the script is stored. When you are in that folder can you execute the following to verify if the file is still functional:
      . .\Get-RemoteProgram.ps1;Get-RemoteProgram
      What this does is dot source the script that makes the Get-RemoteProgram function available. If you would like to ensure that the function is always available, then you could load this function on start up by adding this to your personal PowerShell profile.
  • Where to place computers.text file
    6 Posts | Last post October 23, 2015
    • Dumb question, where do I place text file that the scripts reads when it is executed? 
    • You can place the text file wherever you prefer, if you want to use a text file to provide the computer names you could execute the script with something along these lines:
      . .\Get-RemoteProgram.ps1
      Get-Content -Path C:\YourPath\YourInputFile.txt | Get-RemoteProgram
    • Thanks Alot Japp! 
      Another question; is there a way to add, not only the version and versionmajor, but also the OS of the system in question? 
    • Sure that's possible, that information cannot be retrieved by this function. So you could do a WMI query to retrieve that information, here is an example of how to do this:
      . .\Get-RemoteProgram.ps1
      Get-Content -Path C:\YourPath\YourInputFile.txt | ForEach-Object {$Version = (Get-WmiObject -ComputerName $_.ComputerName -Query 'Select Version From Win32_OperatingSystem').Version;Get-RemoteProgram -ComputerName $_ -Property VersionMajor,DisplayVersion | Select-Object *,@{name='OSVersion';expression={$Version}}}
    • what line of the script would I inject this extra code into? would I still be able to use the export feature once its done? 
      Basically, I would like to use the script to be able to pull all the information it already can, plus also identifying OS version. then export this to a list. 
      You have been a great deal of help already! Thanks for your contributions!
    • Hello Agent Blah,
      You do not have to update the script, you can simply execute the code I posted above and the script will get the additional output you require. Basically I just do two things, first I assign the current computer's Build and version number to the $Version variable:
      $Version = (Get-WmiObject -ComputerName $_.ComputerName -Query 'Select Version From Win32_OperatingSystem').Version
      Then I use calculated properties to add this as an additional property:
      | Select-Object *,@{name='OSVersion';expression={$Version}}
      So you can simply execute the code in my previous example you should get the output you requested.
  • Adding the ProductCode
    2 Posts | Last post October 08, 2015
    • Hi Jaap,
      Thank you for sharing this snippet. I have made a minor modification that I thought I should share back. I've run into a situation where a particular UninstallString is incorrect, therefore I needed the ProductCode/PackageID to invoke the correct MSIExec command to remove the program.
      Unfortunately this information is not duplicated in the Subkey so using the -Property tag did not work. However in this script you do have the Subkey name in your hand, as per the MSDN documentation this should be the ProductCode/PackageID (in practice it seems like not everyone follows this, but if its an actual Windows Installer/MSI it will).
      Simply modify the $SelectProperty to contain a new property 'ProductCode' and then add $HashProperty.ProductCode = "$_" after the program name is assigned and you should have what you want.
      You could get a little more tricky and check for the property dynamically in the foreach loop, but this is the path of least resistance.
    • Hello aolszowka,
      I can see how this could be useful, I would actually like to take it one step further and add in a switch that will expose the registry key. This would give you the ability to retrieve the product key from that and it also shows which part of the registry this information is retrieved from SYSWOW or default path.
      Would that be an interesting addition for you?
  • Can you tell me what I need to add to the script in order to word-wrap the ProgramName? Thank you in advance.
    2 Posts | Last post September 21, 2015
    • I'm somewhat new to PowerShell. I was trying different things but could not come up with a good solution. Thank you.
    • Hello Carlos,
      I am afraid I am not sure what you mean by word wrapping in this context. Can you give an example of the output you are currently getting and an example of what you would like to be getting. If you provide me with that information I will most likely be able to help you out with this.
  • How to get the version of only specific Program from this function
    5 Posts | Last post September 03, 2015
    • I am trying with the below code but not getting the result, can u please help!
       Get-InstalledProgram -Property DisplayVersion -ComputerName (Get-Content .\serverlist.txt) -ErrorAction SilentlyContinue | Where-Object {[string]$_.SystemComponent -ne 1 -and ![string]$_.IsMinorUpgrade -and ![string]$_.ReleaseType -and ![string]$_.ParentDisplayName -a
      nd $_.ProgramName -like "*Endpoint*"}  | sort-Object ProgramName -ErrorAction SilentlyContinue
    • Please Note: i just changed get-remoteProgram to get-installedProgram :)
    • Hello Vicky,
      The script by default only retrieves the ProgramName and the ComputerName, any additional properties will have to be retrieved by using the -Property parameter like you were doing with DisplayVersion. Since you are using a Where-Object clause that includes additional properties you should also retrieve those from the registry.
      I rewrote your code to the following:
      Get-RemoteProgram -Property DisplayVersion,SystemComponent,IsMinorUpgrade,ReleaseType,ParentDisplayName -ComputerName (Get-Content .\serverlist.txt) | Where-Object {[string]$_.SystemComponent -ne 1 -and ![string]$_.IsMinorUpgrade -and ![string]$_.ReleaseType -and ![string]$_.ParentDisplayName -and $_.ProgramName -like "*Endpoint*"} | Sort-Object ProgramName
    • Thank you very much Jaap Brasser :)
    • No problem, happy to help. Cool avatar by the way :)
  • Get Version Number Too
    2 Posts | Last post August 13, 2015
    • I changed line 65 and added line 86 as follows:
      Line 65:
      $SelectProperty = @('ProgramName','ProgramVersion','ComputerName')
      Line 86:
      $HashProperty.ProgramVersion = ($DisplayName = ($RegBase.OpenSubKey("$CurrentReg$_")).GetValue('DisplayVersion'))
    • The cool thing about the script is that this is already supported without the need to change the script. All you have to do is run the original script as it is posted here like this:
      Get-RemoteProgram -Property DisplayVersion
      This will get you the same result as editing the script. If it is required to name the column ProgramVersion then you could also do something along these lines:
      Get-RemoteProgram -Property DisplayVersion | Select-Object -Property ProgramName,ComputerName,@{name=ProgramVersion;expression={$_.DisplayName}}
      Let me know how that works for you!
  • 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
51 - 60 of 69 Items