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
(63)
100,351 times
Add to favorites
Operating System
4/9/2018
E-mail Twitter del.icio.us Digg Facebook
Sign in to ask a question


  • Minmizing the list
    4 Posts | Last post August 26, 2016
    • Is there a way or change in the command itself so that when I receive the list of programs it won't be so long? For example, I noticed that you will see duplicates for past update with certain programs. Can I parse this so that similar programs like that will only appear once to make looking at my list easier?
    • You can filter the output however you would like. But 'similar names' is a bit vague. Can you give an example of how the names are similar then I could give you an example of how to filter out the duplicates.
      
      Regards,
      
      Jaap Brasser
    • Absolutely, For instance I am seeing "Microsoft .Net Framework" and "Microsoft Visual C++ 2012" With many versions of their updates. I'm assuming there is a way to filter them out like you said so I would love to know how to do that. However, if there is anyway to minimize these so I could only see one copy to at least visually show that it is there that would be much more beneficial. Thanks!
    • Hello FWK890,
      
      I have taken a look at your issue and I have introduced two new parameters to deal with the issue. I have introduced two new parameters:
          -ExcludeSimilar
          -SimilarWord
      
      So if you execute the script as follows:
      
      Get-RemoteProgram -ExcludeSimilar -SimilarWord 3
      
      This will filter out similar program names, it filters on the first 3 words in a program name. If a program consists of three or less words it is always included. For example if you Visual Studio 2015 installed it will list all the components individually by default, using -ExcludeSimilar will display one entry of Visual Studio 2015.
  • Unable to run
    2 Posts | Last post July 26, 2016
    • hello Jaap,
      
      I'm very new to this scripting world.
      When i'm trying to run the script as:
      
      Get-RemoteProgram -ComputerName "Laptop-009"
      
      i got the same error as this post by Joel below. Our computer name has a - in it so i guest i have to user "" for it. not sure if its correct.
      
      Would you please help me figure out how to get this to work as your suggestion below to turn on the RemoteRegistry however i do not know how to do it.
      
      Thanks,
      
      "Joel Calvo
      I'm nearly 100% confident that this script only works if the Remote Registry Service is set to Automatic, or Manual on the target computers. If the service is set to disabled, the output of this script will yield the following error: "Exception calling "OpenRemoteBaseKey" with "2" argument(s): "The network path was not found."
      
      Can you please confirm with me the above information? If the above information is correct, can you please help me determine the best way to integrate the ability to turn on or off the Remote Registry Service on all target computers? I'm using Get-Content CMDLET pathed to a text file containing a list of target machines.
      
      Thanks!
      
      Written April 24, 2016
      Jaap Brasser
      That is correct, the script remotely queries the registry for this information. As for remotely activating the service it really depends how locked down your systems are. Initially I would recommend using the WMI/CIM cmdlets for this purpose:
      
      $Service = Get-WmiObject -Query 'Select * FROM Win32_Service WHERE Name="RemoteRegistry"'
      $Service.ChangeStartMode('Automatic')
      $Service.Start()
      
      Let me know if that works for you."
    • Hello TommyNG,
      
      It almost never hurts to wrap your parameter arguments in quotation marks, but in this case it is not necessary. What kind of environment are you working in, if you are in a domain based environment you could create a group policy that enables remote registry on all systems within your domain.
      
      Alternatively you could run the code in my response to Joel. If you want to run it against a remote system you could include the -ComputerName parameter as such:
      
      $Service = Get-WmiObject -Query 'Select * FROM Win32_Service WHERE Name="RemoteRegistry"' -ComputerName server01
      $Service.ChangeStartMode('Automatic')
      $Service.Start()
      
  • Store values in database?
    2 Posts | Last post July 26, 2016
    • Hello,
      
      Is it possible to use this script to store values in a database? For example, if I wanted to get a list of all the applications on all of my domain computers and then run queries against them?
    • Absolutely, there are many tools available to interact with SQL databases, have a look at DBATools:
      https://github.com/ctrlbold/dbatools
      
      My advice would be to query and export to csv and then to import the csv into a SQL database to make it avaialble that way.
  • Changing order of displayed properties
    2 Posts | Last post May 05, 2016
    • I cannot seem to find a way to modify the order that the returned properties are displayed.  
      
      I'm exporting the output to a .csv file, and want the first column to be the ComputerName.  I feel like an idiot asking this, but can you please point me in the right direction? TIA
    • This is something that can be done using the Select-Object cmdlet, for example if you would like to display the computername first you could do something along these lines:
      
      Get-RemoteProgram | Select-Object -Property ComputerName,ProgramName
      
      And I would go as far as calling you an idiot, you are learning and not afraid to ask so at least you learned something today :) If you would like to know more about PowerShell and a large selection of resources to learn more about PowerShell head on over here:
      http://www.jaapbrasser.com/how-to-learn-powershell
  • Basic Use
    4 Posts | Last post April 24, 2016
    • Jaap,
      
      I'm a pretty big powershell noob, do you have a quick tutorial on how I can exceute this one one PC on my network. I'm familiar with basics get-commands but this is kinda verbose.
      
      Thanks,
      
      Kyle
    • Kyle,
      
      Follow the instructions in his description.
      
      1) Open a PowerShell window
      
      2) Use the CD command to Change Directory of PowerShell session to the directory where the Get-RemoteProgram.ps1 file resides. For example, if the .ps1 file resides in C:\Scripts, then run CD C:\Scripts
      
      3) Run the following command next:
      
      Get-RemoteProgram -ComputerName HOSTNAME
      
      Where it says HOSTNAME, you'd replace that with the target machine hostname.
    • Joel,
      
      Thanks, I was able to execute the command without error, but after it completed there was no output in my powershell session. Does the script save a log file somewhere? I've searched through it and can't find anything in the script that specifies anything of the sort.
    • I think in the instructions by Joel Calvo were quite accurate, thanks for that Joel. One step was missing however, so for step 3 could you execute this:
      
      .\Get-RemoteProgram;Get-RemoteProgram -ComputerName HOSTNAME
      
      Let me know if that works better.
      
      
      Regards,
      
      Jaap Brasser
  • Question regarding this script+Remote Registry Service
    2 Posts | Last post April 24, 2016
    • I'm nearly 100% confident that this script only works if the Remote Registry Service is set to Automatic, or Manual on the target computers. If the service is set to disabled, the output of this script will yield the following error: "Exception calling "OpenRemoteBaseKey" with "2" argument(s): "The network path was not found."
      
      Can you please confirm with me the above information? If the above information is correct, can you please help me determine the best way to integrate the ability to turn on or off the Remote Registry Service on all target computers? I'm using Get-Content CMDLET pathed to a text file containing a list of target machines.
      
      Thanks!
    • That is correct, the script remotely queries the registry for this information. As for remotely activating the service it really depends how locked down your systems are. Initially I would recommend using the WMI/CIM cmdlets for this purpose:
      
      $Service = Get-WmiObject -Query 'Select * FROM Win32_Service WHERE Name="RemoteRegistry"'
      $Service.ChangeStartMode('Automatic')
      $Service.Start()
      
      Let me know if that works for you.
      
  • The script doesn't output anything
    2 Posts | Last post April 24, 2016
    • As we heavily lock down workplaces, and amongst others the remote registry service
      was not started. I don't get a single error, the output is just blank, I run it on my local desktop with Administrative rights. I changed the execution policy.
      I see it queries [Microsoft.Win32.RegistryKey], I was wondering is there some .NET version required to operate this ? 
      The script is very usefull ..... I hope to get it up and running.
      
    • Hello Steft,
      
      If the .Net classes are missing it should definitely prompt for errors, could you check the $Error variable to see if there aren't any errors in there. The MSDN entry for this class shows that it has at least been present since .Net 1.1, so that should not be a problem.
      
      If the remote registry is not running that is an issue, as the script relies on the availability of that. Can you verify that the remote registry service is available on the system you are querying?
  • Question on placement in Powershell Script
    4 Posts | Last post April 15, 2016
    • For the below:
      Get-Content -Path C:\test\servers.Txt | ForEach-Object -Begin {
          . .\Get-RemoteProgram.ps1 
      } -Process {
          Get-RemoteProgram -ComputerName $_ -Property InstallDate,Version
      } | Where-Object {$_.ProgramName -like 'Microsoft Silverlight*'}
      
      Where would I place this in the script to get it functioning properly?  We are looking to get the same information here and this is most helpful so far.  In addition, am wanting to utilize a list of servers, which the servers.txt in the above would accomplish, correct?
      
      Appreciate any assistance that can be provided, still learning PowerShell scripting.
    • You would not put this in the script, this would be one of the ways to execute the script. If you would like you could store this in another script file in order to more easily call the script or create a custom alias or a function, but I would not recommend modifying the script in order to get this output.
      
      Here is a less verbose, shorter version by using aliases:
      cat C:\test\servers.Txt|%{. .\Get-RemoteProgram.ps1} {Get-RemoteProgram -C $_ -P InstallDate,Version}|?{$_.ProgramName -like 'Microsoft Silverlight*'}
      
      So my question now is, why would you want to store this inside of the script? What are you trying to accomplish then I can think along with you and give you some suggestions based on that.
      
    • What I was wanting to include in the script is to have it pull the install date and version information by default.  Using a file for the server list is the best way for me to run the script.  
    • One of methods you could use is to set the default parameter values using $PSDefaultParameterValues, to read more about using that you can type the following:
      Get-Help about_Parameters_Default_Values
      Or visit the following website:
      https://technet.microsoft.com/en-us/library/hh847819.aspx
      
      If you want to edit the script, I suggest you edit line 56 and 58 in the parameter block to set the default there:
      $ComputerName = (cat c:\test\servers.txt),
      [string[]]$Property = @('InstallDate','Version')
  • Adding Display Version
    4 Posts | Last post April 14, 2016
    • Hi Japp,
      
      How can we take InstalledDate and Version of the product from the below query. I  have tried to add InstalledDate and Version but no result.
      
      Thanks in Advance.
      
      Get-Content -Path C:\test\servers.Txt | ForEach-Object -Begin {
          . .\Get-RemoteProgram.ps1 
      } -Process {
          Get-RemoteProgram -ComputerName $_
      } | Where-Object {$_.ProgramName -like 'Microsoft Silverlight*'} | select -Property ComputerName,ProgramName -Unique
    • Hello Syed Kaliff,
      
      What you could do is the following:
      
      Get-Content -Path C:\test\servers.Txt | ForEach-Object -Begin {
          . .\Get-RemoteProgram.ps1 
      } -Process {
          Get-RemoteProgram -ComputerName $_ -Property InstallDate,Version
      } | Where-Object {$_.ProgramName -like 'Microsoft Silverlight*'}
      
      Do note that not all properties might be displayed in the console depending on your PowerShell. If you want to ensure all properties are visible in the console you could use the Format-* cmdlets, if you would like to view the output outside of the console you could export it to csv/xml/json.
      
      Let me know if this helps.
    • Thanks Japp,
      
      Its working fine :)
    • I am glad to hear that Syed, thanks for confirming that the solution works as intended. Have fun scripting today!
      
      
      Regards,
      
      Jaap Brasser
  • Possible to exclude certain entries on the list?
    13 Posts | Last post April 12, 2016
    • Is it possible to exclude an array of entries from the list of programs. This pulls all the programs in the uninstall registry location, such as all the windows updates and some unnecessary programs.  
      
      
    • Absolutely, you could pipe the results of Get-RemoteProgram into the Where-Object cmdlet to filter the results. For example to filter any program that contains KB000000 notation you could use the following code:
      
      Get-RemoteProgram | Where-Object {$_.ProgramName -notmatch 'KB\d+'}
      
      Alternatively you could include the SystemComponent or the IsMinorUpgrade properties and filter on that:
      
      Get-RemoteProgram -Property SystemComponent | Where-Object {-not $_.SystemComponent}
      
      Get-RemoteProgram -Property IsMinorUpgrade | Where-Object {-not $_.IsMinorUpgrade}
    • Thank you for the quick reply Jaap! This is so useful!
    • No problem, happy to help let me know if you have any additional question.
      
      Regards,
      
      Jaap Brasser
    • Hi Japp, 
      
      I do have another question. So I am trying to exclude a bigger list of programs. Right now I am just piping the where-object for each program I want exclude.
      i.e.
      
      Get-RemoteProgram -computername $computerName -property SystemComponent | Where-Object {$_.ProgramName -notmatch 'KB\d+'} | where-object {-not $_.SystemComponent} | where-object {$_.programName -notmatch 'Microsoft Visual*'} | where-object {$_.programName -notmatch 'Driver*'} | where-object {$_.programName -notmatch 'Microsoft Application Virtualization*'} |
      where-object {$_.programName -notmatch 'Adobe Reader XI'} | where-object {$_.programName -notmatch 'Adobe Shockwave Player 11.5'} | where-object {$_.programName -notmatch 'Crystal Reports Viewer 2008'} |where-object {$_.programName -notmatch 'OMM_*'} | sort-object -property programName | Format-Table -Property programName, InstallDate -autosize
    • Sure so to start what you could do is combine this into a single Where-Object cmdlet, you can use the -and and -or parameters, for example you could shorten your command to this:
      
      Get-RemoteProgram -computername $computerName -property SystemComponent | Where-Object {($_.ProgramName -notmatch 'KB\d+') -and (-not $_.SystemComponent) -and ($_.programName -notlike 'Microsoft Visual*') -and ($_.programName -notlike 'Driver*') -and ($_.programName -notlike 'Microsoft Application Virtualization*') -and ($_.programName -notlike 'Adobe Reader XI') -and ($_.programName -notlike 'Adobe Shockwave Player 11.5') -and ($_.programName -notlike 'Crystal Reports Viewer 2008') -and ($_.programName -notlike 'OMM_*')} | sort-object -property programName | Format-Table -Property programName, InstallDate -autosize
      
      Now this is still a long command, most of this comes from the fact that there is no comparison operator that matches on regular expressions. I noticed that you used the *-symbol in your example, so I assumed you meant to use the -like operator rather than the -match operator. In the next example I have created an array of statements to compare against, this makes it easier to later add additional programs, for example something along these lines:
      
      $Regexes = 'Microsoft Visual*','Driver*','Microsoft Application Virtualization*','Adobe Reader XI','Adobe Shockwave Player 11.5','Crystal Reports Viewer 2008','OMM_*'
      Get-RemoteProgram -ComputerName $computerName -Property SystemComponent | Where-Object {($_.ProgramName -notmatch 'KB\d+') -and (-not $_.SystemComponent) -and $($ProgramName=$_.ProgramName;if (($Regexes | ForEach-Object {$ProgramName -notlike $_}) -contains $false) {$false} else {$true})}
    • The array is exactly what i was looking for. Thanks again Jaap!
    • No problem, happy to help!
      
      If you are interested we could even simplify this further by using regular expressions.
      
      
      Regards,
      
      Jaap Brasser
    • I would definitely be interested in that. Anything to simplify a code is good value :).
    • Alright, here is an example entirely based on regex in combination with SystemComponent:
      
      $RegEx = 'KB\d+|^Microsoft Visual.*|^Driver.*|^Microsoft Application Virtualization.*|^Adobe Reader XI|Adobe Shockwave Player 11.5|Crystal Reports Viewer 2008|OMM_.*'
      Get-RemoteProgram -computername $computerName -property SystemComponent | Where-Object {($_.ProgramName -notmatch $RegEx) -and (-not $_.SystemComponent)}
      
      I am not sure how familiar you are with regular expressions, so let me know if you need any explanation of the regular expression as I have defined it above. What I did is make a regular expressions that matches your like expressions as closely as possible. Let me know if this works for you.
    • I understand off the regex in $RegEx except for the first one "KB\d+". Can you explain this one.
    • Disregard my last comment. I understand all of it now. Thanks Jaap!
      
      I do have another issue. I'm trying to export my list to a csv, but I'm getting guid's as the program name and my other columns don't even show up.
      
      This is my code:
      
      $Regexes = 'Microsoft Visual*','Driver*','Microsoft Application Virtualization*','Adobe Reader XI (11.0.09)','Adobe Shockwave Player 11.5','Crystal Reports Viewer 2008','OMM_*', 'Google Chrome', 'API Calculator 3.3.0.0', 'EnCompass', 'Junos Pulse 5.0', 'Microsoft Office 2010 Primary Interop Assemblies', 'Microsoft Office Professional Plus 2010', 'McAfee*', 'Adobe Flash Player 20*', 'Adobe Shockwave Player*', 'HP Hotkey Support', 'Juniper*', 'TRAC 2', 'Training and Certification*', 'Microsoft Lync 2013','OM Manuals', 'SCCM Log File Folder', 'Blueprint Tracker Installer', 'Diskeeper 12 Professional', 'Microsoft OneDrive*', 'System Center Configuration Manager Console', 'Carbon Black Sensor', 'Globalscape Mail Express Outlook Addin'
      Get-RemoteProgram -ComputerName $computer -Property SystemComponent | 
                                  Where-Object {
                                      ($_.ProgramName -notmatch 'KB\d+') -and (-not $_.SystemComponent) -and $($ProgramName=$_.ProgramName;
                                          if (($Regexes | ForEach-Object {$ProgramName -notlike $_}) -contains $false) 
                                              {
                                                  $false
                                              } 
                                          else 
                                              {
                                                  $true
                                              }
                                          )
                                  } | sort-object -property programName | Format-Table -Property programName, InstallDate -autosize | Export-Csv -Path C:\temp\test.csv -NoTypeInformation
    • Hello Richard,
      
      I will answer your first question as a reference for anyone reading back on this later, the regular expression:
      KB\d+
      
      The letter KB stand for the letters KB \d+ stands for a number and + means one or more. This means that it will match for KB followed by 1 or more numbers.
      
      As for your second question the problem is with Format-Table, or actually any of the Format-* parameters in PowerShell. If you format output it will look pretty in the console but you will no longer be able to process it as structured data. This is because the actual objects are converted to a special formatted type that displays well in the PowerShell console. So you would get the output your expect if you remove the following bit from your code:
      
      | Format-Table -Property programName, InstallDate -autosize
      
      Let me know if that answers your questions.
31 - 40 of 69 Items