PoshCode Logo PowerShell Code Repository

Get-Software Function by Geoffrey Guynn 4 weeks ago
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/3186"></script>download | new post

I was having a great deal of difficulty in properly enumerating software applications on remote machines, so I wrote this function to help ease the problem somewhat. Among the many methods of gathering this information that are available, I had the most success using the “SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall” registry key as an information source. In order to use this function, the Powershell instance must support .Net 4.0 or greater, which is fairly straightforward if you follow these instructions.
1. Open notepad and copy the below text exactly as shown into the document.

<?xml version=“1.0”?>
<configuration> <startup useLegacyV2RuntimeActivationPolicy=“true”> <supportedRuntime version=“v4.0.30319”/> <supportedRuntime version=“v2.0.50727”/> </startup>
</configuration>

2. Save this document as c:\windows\System32\WindowsPowerhsell\v1.0\Powershell.exe.config (or c:\windows\System32\WindowsPowerhsell\v1.0\Powershell_ise.exe.config)
3. Reload powershell and type the following command: $PsVersionTable.clrVersion (It should show Major version 4 if .Net 4 is supported.)

Take note that this release does not contain error checking functions that my production version uses, I removed references to these functions in order to provide a good starting function for others to use. If you have any errors with this code, please contact me and I will resolve them as soon as possible.

  1. Function Get-Software{
  2.     <#
  3.     .SYNOPSIS
  4.         Gets the software applications on a remote computer.
  5.     .DESCRIPTION
  6.         This function interrogates the remote registry for installed software products.
  7.         It then returns an array of powershell objects that can be sorted and parsed.
  8.        
  9.         Optionally, you can provide a product name that will filter applications based on
  10.         displayname before they are returned, thus reducing the typing needed to get specific results.
  11.     .PARAMETER computer
  12.         The name of the computer to retrieve a software list from.
  13.     .PARAMETER product
  14.         The partial name of a software application to search for.
  15.     .INPUTS
  16.     .OUTPUTS
  17.     .NOTES
  18.         Name: Get-Software
  19.         Author: Geoffrey Guynn
  20.         DateCreated 9 Aug 2011
  21.     .EXAMPLE
  22.         Get-Software -computer "computer" -name "Adobe"
  23.         Returns all instances of Adobe software on the computer.
  24.     #>
  25.  
  26.     [cmdletbinding(
  27.         SupportsShouldProcess = $True,
  28.         DefaultParameterSetName = "process",
  29.         ConfirmImpact = "low"
  30.     )]
  31.     param(
  32.         [ValidateNotNullOrEmpty()]
  33.         [string]$Computer
  34.         ,
  35.         [string]$Product
  36.     )
  37.     #Get Architechture Type of the system
  38.     $OSArch = (Gwmi -computer $Computer win32_operatingSystem).OSArchitecture
  39.     if ($OSArch -like "*64*") {$Architectures = @("32bit","64bit")}
  40.     else {$Architectures = @("32bit")}
  41.     #Create an array to capture program objects.
  42.     $arApplications = @()
  43.     foreach ($Architecture in $Architectures){
  44.         #We have a 64bit machine, get the 32 bit software.
  45.         if ($Architecture -like "*64*"){
  46.             #Define the entry point to the registry.
  47.             $strSubKey = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
  48.             $SoftArchitecture = "32bit"
  49.             $RegViewEnum = [Microsoft.Win32.RegistryView]::Registry64
  50.         }
  51.         #We have a 32bit machine, use the 32bit registry provider.
  52.         elseif ($Architectures -notcontains "64bit"){
  53.             #Define the entry point to the registry.
  54.             $strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
  55.             $SoftArchitecture = "32bit"
  56.             $RegViewEnum = [Microsoft.Win32.RegistryView]::Registry32
  57.         }
  58.         #We have "64bit" in our array, capture the 64bit software.
  59.         else{
  60.             #Define the entry point to the registry.
  61.             $strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
  62.             $SoftArchitecture = "64bit"
  63.             $RegViewEnum = [Microsoft.Win32.RegistryView]::Registry64
  64.         }
  65.         #The standard routine to get software.
  66.         #************************************************************************
  67.         #Create a remote registry connection to the server.
  68.         $remRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer, $RegViewEnum)
  69.         #Open the entry point.
  70.         $remKey = $remRegistry.OpenSubKey($strSubKey)
  71.         #Get all subkeys that exist in the entry point.
  72.         $remSoftware = $remKey.GetSubKeyNames()
  73.         #Loop through the applications and capture data.
  74.         foreach ($remApplication in $RemSoftware){
  75.             $remProgram = $remRegistry.OpenSubKey("$strSubKey\\$remApplication")
  76.             $strDisplayName = $remProgram.GetValue("DisplayName")
  77.             if ($strDisplayName){
  78.                 #Get a list of all available properties for the program.
  79.                 $arProperties = $remProgram.GetValueNames()
  80.                 #Create a custom object for this program.
  81.                 $objApplication = New-Object System.Object
  82.                 #Write-Host "`n"
  83.                 foreach ($strProperty in $arProperties){
  84.                     #Get the value associated with the current property.
  85.                     $strValue = [string]($remProgram.GetValue($strProperty))
  86.                     if ($strValue){
  87.                         #If the property has a value but no name, then it is the default property.
  88.                         if (!$strProperty){
  89.                             $objApplication | Add-Member -type NoteProperty -Name "(Default)" -Value $strValue
  90.                         }
  91.                         #The property has a value and a name, assign them both as a new property on the object.
  92.                         else{
  93.                             $objApplication | Add-Member -type NoteProperty -Name ([string]$strProperty) -Value $strValue
  94.                         }
  95.                     }
  96.                     #Write-Host $strValue ": " $remProgram.GetValue($strValue)
  97.                 }
  98.                 #Add a final property to denote the software architecture type.
  99.                 $objApplication | Add-Member -type NoteProperty -Name "Architecture" -Value $SoftArchitecture
  100.                 #Add the last application to the array of programs.
  101.                 $arApplications += $objApplication
  102.             }
  103.         }
  104.     }
  105.     if ($Product){
  106.         $objApplication = $arApplications | ? {$_.DisplayName -Like "*$Product*"} | Sort-Object -property Architecture,DisplayName
  107.         return $objApplication
  108.     }
  109.     #Sort the array by each object's Architecture and DisplayName.
  110.     $arApplications = $arApplications | Sort-Object -property Architecture,DisplayName
  111.     return $arApplications
  112. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me