PowerShell – query installed software on remote computers

You can probably find plenty of PowerShell scripts that will retrieve a list of installed software on a local or a remote computer. Most of them utilize two techniques for detecting installed software from a computer:

  • Registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall key
  • Win32_Product Class

Please note that the Win32_Product class has some limitations:

1. It retrieves only the names of applications installed using the Windows Installer service.
2. Retrieving instances of the Win32_Product class is very slow.
3. It’s not always possible to retrieve Win32_Product class instances from remote computers.
Luckily, we can obtain information about installed software from a computer’s registry instead. Please be aware that in some environments the RemoteRegistry service (enabled by default) would be disabled if the High Security Policy Template was applied, and in such case your script would need to enable this service first, and then enumerate the Uninstall key and read the data in each subkey underneath the Uninstall key.

My Example:  Query-SoftwareOnRemotePc.ps1

I need to regularly audit if the specific software (and its version) has been installed on the computers in the particular Active Directory OU that has High Security Policy Template applied, and export it to a list of software. For this reason, my script first enables RemoteRegistry service and then generates a list by querying the registry and returning the specific programs (note in the script the section where I query only specific subkeys: SEP and Flash Player) from remote computers. The script exports the list of software to .CSV file and creates a log file. The next time the script runs, it will query only the computers in Active Directory OU that could not be reached / queried in the previous attempt. Check the script below:


# Filename: Query-SoftwareOnRemotePc_ADSI.ps1 
# Date:     July, 2014
# Author:   Alex Dujakovic 
# Description: PowerShell script to get the list of software installed on remote computers
# In a loop, an array receives a lot of new items using the operator "+="
# to speed up this array operation, in this example I will use ArrayList
#------------------------------------------------------------------------------------------------------
$myOU = [ADSI]"LDAP://OU=AFL-Computers,OU=AFL,OU=Accounts,DC=Test,DC=com"
$logFile="C:\PScontainer\QueryInstalledSoftwareLog.log"
$csvFilePath = "C:\PScontainer\SoftwareList.csv"
# Check if .CSV file exist, and create empty one with column names of the software I am searching for
if (!(Test-Path -path $csvFilePath)) { ""|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion | 
 Export-Csv -Path $csvFilePath -NoTypeInformation}

$outputArray = New-Object -TypeName System.Collections.ArrayList

$PCcollection = ($myOU.psbase.Children | Where  -FilterScript{$_.ObjectCategory -Like "*Computer*"} | 
 Select-Object -ExpandProperty Name)
$reachedPCs = (Import-Csv -Path $csvFilePath | Select-Object -ExpandProperty Name)

$newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs |
Where-Object -FilterScript {$_.SideIndicator -eq "<="} |Select-Object -ExpandProperty InputObject | Sort InputObject)

foreach ($pcItem In $newQueryCollection){
Write-Host "Pinging computer: $pcItem" # comment this line if you do not want to see the names of computers
If (Test-Connection -ComputerName $pcItem -ea silentlycontinue -Count 1) {
          try 
            { 
            $errorActionPreference = "Stop"
            Write-Host "Querying computer: $pcItem" -ForegroundColor Green # comment this line if you do not want to see the names of computers
            "$($pcItem) - Success" | Out-file -FilePath $logFile -Encoding ascii -Append
            (Get-WmiObject -computerName $pcItem Win32_Service -Filter "Name='RemoteRegistry'").StartService() | Out-Null
            $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$pcItem)
            $RegKeySEP= $Reg.OpenSubKey("SOFTWARE\\Symantec\\Symantec Endpoint Protection\\CurrentVersion")
            $VersionSEP = $RegKeySEP.GetValue("PRODUCTVERSION")
            $RegKeyFP= $Reg.OpenSubKey("SOFTWARE\\Macromedia\\FlashPlayer")
            $VersionFP = $RegKeyFP.GetValue("CurrentVersion")
            $RegKeyFPPlug= $Reg.OpenSubKey("SOFTWARE\\Macromedia\\FlashPlayerPlugin")
            $VersionFPlug = $RegKeyFPPlug.GetValue("Version")
            $row = ""|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion
            $row.Name = $pcItem.ToString()
            $row.SEP = "Symantec Endpoint Protection"
            $row.SEPVersion = $VersionSEP
            $row.FlashPlayer = "Flash Player"
            $row.FPlayerVersion = $VersionFP
            $row.FPPlugin = "Flash Player Plugin"
            $row.FPPluginVersion = $VersionFPlug
            $outputArray.Add($row)
            Remove-Variable Reg,VersionSEP, VersionFP, VersionFPlug
            }

         catch 
            { 
             "$($pcItem) -(ERROR)- Exception Type: $($_.Exception.GetType().FullName)" | 
               Out-file -FilePath $logFile -Encoding ascii -Append            
            }
       }
       else
        {"$($pcItem) -Ping Failed" | Out-file -FilePath $logFile -Encoding ascii -Append }    
}

$outputArray | Export-Csv -Path $csvFilePath -NoTypeInformation -Append
Write-Host "Script finished execution" -ForegroundColor Red

This is the .CSV file that is created by the script – picture below:

CSVFile

And this is the log file that lists all the results of the script execution – picture below:

LogFile

In the scrip above, I would like to draw your attention to the two following sections. The first one, if you have PowerShell module installed on your computer you will have option to Import-Module ‘ActiveDirectory’ and use the following section in this script:


Import-Module ActiveDirectory
$myOU = "OU=AFL-Computers,OU=AFL,OU=Accounts,DC=Test,DC=com"

$PCcollection = (Get-ADComputer -Filter {(Name -like "AFL-*")} -SearchBase $myOU -Properties Name |
 Select-Object -ExpandProperty Name |Sort)
$reachedPCs = (Import-Csv -Path $csvFilePath | Select-Object -ExpandProperty Name)

Otherwise you can use ADSI to get your computers collections as shown in the first script above.

The second one, it applies to an array in a loop. To speed up an array, which takes a lot of time using the operator “+=”, you should try to use ArrayList, as follows:


$outputArray = New-Object -TypeName System.Collections.ArrayList
$row = ""|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion
            $row.Name = $pcItem.ToString()
            $row.SEP = "Symantec Endpoint Protection"
            $row.SEPVersion = $VersionSEP
            $row.FlashPlayer = "Flash Player"
            $row.FPlayerVersion = $VersionFP
            $row.FPPlugin = "Flash Player Plugin"
            $row.FPPluginVersion = $VersionFPlug
$outputArray.Add($row)

The Query-SoftwareOnRemotePc.ps1 scripts (both versions: ADSI and ActiveDirectory module) could be found in the download section, under PowerShell.





Please note: Although the author has made every reasonable attempt to achieve complete accuracy of the content, he assumes no responsibility for errors or omissions. Also, you should use this information as you see fit, and at your own risk.

14 thoughts on “PowerShell – query installed software on remote computers

  1. Kuldeep

    Hi,
    I have no idea of Powershell. want user this script (PowerShell – query installed software on remote computers) in my enviroment. Due to large number of OUs in multiple domains, i don’t want to use importing systems from OU.

    Here i want here in script, i just give name of systems through the txt file as input. Please help me on this.

    Reply
    1. admin Post author

      In this script I used OU to create collection of computers that will be queried for installed software. If you want to use a list with the computers instead, than you will use Get-Content cmdlet. For example you have a file with all computer names you want to query, in my example the PcList.txt file (C:\Test\PcList.txt) contains the computer names as follows:
      Halifax-01
      Dartmouth-02
      Bedford-03
      Dartmouth-04
      Dartmouth-05
      Bedford-07
      Dartmouth-09

      Now to query these computers, I would use the following lines of script:

      $logFile=”C:\PScontainer\QueryInstalledSoftwareLog.log”
      $csvFilePath = “C:\PScontainer\SoftwareList.csv”
      # Check if .CSV file exist, and create empty one with column names of the software I am searching for
      if (!(Test-Path -path $csvFilePath)) { “”|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion |
      Export-Csv -Path $csvFilePath -NoTypeInformation}

      $outputArray = New-Object -TypeName System.Collections.ArrayList
      # NOTE: This file contains the list of your computers
      $PCcollection = (Get-Content -Path C:\Test\PcList.txt)
      $reachedPCs = (Import-Csv -Path $csvFilePath| Select-Object -ExpandProperty Name)
      $newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs |
      Where-Object -FilterScript {$_.SideIndicator -eq “<="} | Select-Object -ExpandProperty InputObject | Sort InputObject) foreach ($pcItem In $newQueryCollection){ Write-Host "Pinging computer: $pcItem" # comment this line if you do not want to see the names of computers If (Test-Connection -ComputerName $pcItem -ea silentlycontinue -Count 1) { try { $errorActionPreference = "Stop" Write-Host "Querying computer: $pcItem" -ForegroundColor Green # comment this line if you do not want to see the names of computers "$($pcItem) - Success" | Out-file -FilePath $logFile -Encoding ascii -Append (Get-WmiObject -computerName $pcItem Win32_Service -Filter "Name='RemoteRegistry'").StartService() | Out-Null $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$pcItem) $RegKeySEP= $Reg.OpenSubKey("SOFTWARE\\Symantec\\Symantec Endpoint Protection\\CurrentVersion") $VersionSEP = $RegKeySEP.GetValue("PRODUCTVERSION") $RegKeyFP= $Reg.OpenSubKey("SOFTWARE\\Macromedia\\FlashPlayer") $VersionFP = $RegKeyFP.GetValue("CurrentVersion") $RegKeyFPPlug= $Reg.OpenSubKey("SOFTWARE\\Macromedia\\FlashPlayerPlugin") $VersionFPlug = $RegKeyFPPlug.GetValue("Version") $row = ""|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion $row.Name = $pcItem.ToString() $row.SEP = "Symantec Endpoint Protection" $row.SEPVersion = $VersionSEP $row.FlashPlayer = "Flash Player" $row.FPlayerVersion = $VersionFP $row.FPPlugin = "Flash Player Plugin" $row.FPPluginVersion = $VersionFPlug $outputArray.Add($row) Remove-Variable Reg,VersionSEP, VersionFP, VersionFPlug } catch { "$($pcItem) -(ERROR)- Exception Type: $($_.Exception.GetType().FullName)" | Out-file -FilePath $logFile -Encoding ascii -Append } } else {"$($pcItem) -Ping Failed" | Out-file -FilePath $logFile -Encoding ascii -Append } } $outputArray | Export-Csv -Path $csvFilePath -NoTypeInformation -Append Write-Host "Script finished execution" -ForegroundColor Red Good luck.

      Reply
  2. Tech blogger

    iam getting this error “Cannot bind argument to parameter ‘ReferenceObject’ because it is null.
    At :line:22 char:56
    + $newQueryCollection = (Compare-Object -ReferenceObject $ <<<< PCcollection -DifferenceObject $reachedPCs |"

    Below the script, where iam trying to input the computer names from a text file.
    Please provide me a solution

    # Filename: Query-SoftwareOnRemotePc_ADSI.ps1
    # Date: July, 2014
    # Author: Alex Dujakovic
    # Description: PowerShell script to get the list of software installed on remote computers
    # In a loop, an array receives a lot of new items using the operator "+="
    # to speed up this array operation, in this example I will use ArrayList
    #——————————————————————————————————
    #$myOU = [ADSI]"LDAP://OU=Computers,OU=IN01,OU=IN,OU=ITR08,DC=eurofins,DC=local"
    $PCcollection = (Get-Content -Path C:\Computers.txt)
    $logFile="C:\QueryInstalledSoftwareLog.log"
    $csvFilePath = "C:\SoftwareList.csv"
    # Check if .CSV file exist, and create empty one with column names of the software I am searching for
    if (!(Test-Path -path $csvFilePath)) { ""|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion | Export-Csv -Path $csvFilePath -NoTypeInformation}
    $outputArray = New-Object -TypeName System.Collections.ArrayList
    $PCcollection = ($computer | Where -FilterScript{$_.ObjectCategory -Like "*Computer*"} |
    Select-Object -ExpandProperty Name)
    $reachedPCs = (Import-Csv -Path $csvFilePath | Select-Object -ExpandProperty Name)
    $newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs |
    Where-Object -FilterScript {$_.SideIndicator -eq "<="} |Select-Object -ExpandProperty)

    Reply
    1. admin Post author

      The problem in this block of code is the line where you use $computer variable (any unassigned variable will have a value of null, not a data type of null):

      $PCcollection = (Get-Content -Path C:\Computers.txt)
      $logFile=”C:\QueryInstalledSoftwareLog.log”
      $csvFilePath = “C:\SoftwareList.csv”
      # Check if .CSV file exist, and create empty one with column names of the software I am searching for
      if (!(Test-Path -path $csvFilePath)) { “”|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion | Export-Csv -Path $csvFilePath -NoTypeInformation}
      $outputArray = New-Object -TypeName System.Collections.ArrayList
      # //==> unassigned variable $computer will have a value of null
      $PCcollection = ($computer | Where -FilterScript{$_.ObjectCategory -Like “*Computer*”} |
      Select-Object -ExpandProperty Name)
      $reachedPCs = (Import-Csv -Path $csvFilePath | Select-Object -ExpandProperty Name)
      $newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs |
      Where-Object -FilterScript {$_.SideIndicator -eq “<="} |Select-Object -ExpandProperty) Please use the following block of code: $logFile="C:\QueryInstalledSoftwareLog.log" $csvFilePath = "C:\SoftwareList.csv" # Check if .CSV file exist, and create empty one with column names of the software I am searching for if (!(Test-Path -path $csvFilePath)) { ""|Select Name, SEP, SEPVersion, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion | Export-Csv -Path $csvFilePath -NoTypeInformation} $outputArray = New-Object -TypeName System.Collections.ArrayList # NOTE: This file contains the list of your computers $PCcollection = (Get-Content -Path C:\Computers.txt) $reachedPCs = (Import-Csv -Path $csvFilePath| Select-Object -ExpandProperty Name) $newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs | Where-Object -FilterScript {$_.SideIndicator -eq “<="} |Select-Object -ExpandProperty InputObject | Sort InputObject) In addition, check the solution that was given in the first comment.

      Reply
  3. Torie Gowler

    Thanks, I have been seeking for details about this subject matter for ages and yours is the best I’ve discovered so far.

    Reply
  4. Pratik

    # Filename: Query-SoftwareOnRemotePc_ADSI.ps1
    # Date: July, 2014
    # Author: Alex Dujakovic
    # Description: PowerShell script to get the list of software installed on remote computers
    # In a loop, an array receives a lot of new items using the operator “+=”
    # to speed up this array operation, in this example I will use ArrayList
    #——————————————————————————————————
    $logFile=”C:\Users\PSAVALIY\Desktop\QueryInstalledSoftwareLog.log”
    $csvFilePath = “C:\Users\PSAVALIY\Desktop\SoftwareList.csv”

    # Check if .CSV file exist, and create empty one with column names of the software I am searching for
    if (!(Test-Path -path $csvFilePath)) { “”|Select Name, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion |
    Export-Csv -Path $csvFilePath -NoTypeInformation}
    $outputArray = New-Object -TypeName System.Collections.ArrayList
    $PCcollection = (Get-Content -Path C:\Users\PSAVALIY\Desktop\PcList.txt)
    $reachedPCs = (Import-Csv -Path $csvFilePath | Select-Object -ExpandProperty Name)

    $newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs |
    Where-Object -FilterScript {$_.SideIndicator -eq “<="} |Select-Object -ExpandProperty InputObject | Sort InputObject)

    foreach ($pcItem In $newQueryCollection){
    Write-Host "Pinging computer: $pcItem" # comment this line if you do not want to see the names of computers
    If (Test-Connection -ComputerName $pcItem -ea silentlycontinue -Count 1) {
    try
    {
    $errorActionPreference = "Stop"
    Write-Host "Querying computer: $pcItem" -ForegroundColor Green # comment this line if you do not want to see the names of computers
    "$($pcItem) – Success" | Out-file -FilePath $logFile -Encoding ascii -Append
    (Get-WmiObject -computerName $pcItem Win32_Service -Filter "Name='RemoteRegistry'").StartService() | Out-Null
    $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$pcItem)
    $RegKeyFP= $Reg.OpenSubKey("SOFTWARE\\Macromedia\\FlashPlayer")
    $VersionFP = $RegKeyFP.GetValue("CurrentVersion")

    $RegKeyFPPlug= $Reg.OpenSubKey("SOFTWARE\\Macromedia\\FlashPlayerPlugin")
    $VersionFPlug = $RegKeyFPPlug.GetValue("Version")
    $row = ""|Select Name, FlashPlayer, FPlayerVersion, FPPlugin, FPPluginVersion
    $row.Name = $pcItem.ToString()
    $row.SEP = "Symantec Endpoint Protection"
    $row.SEPVersion = $VersionSEP
    $row.FlashPlayer = "Flash Player"
    $row.FPlayerVersion = $VersionFP
    $row.FPPlugin = "Flash Player Plugin"
    $row.FPPluginVersion = $VersionFPlug
    $outputArray.Add($row)
    Remove-Variable Reg,VersionSEP, VersionFP, VersionFPlug
    }

    catch
    {
    "$($pcItem) -(ERROR)- Exception Type: $($_.Exception.GetType().FullName)" |
    Out-file -FilePath $logFile -Encoding ascii -Append
    }
    }
    else
    {"$($pcItem) -Ping Failed" | Out-file -FilePath $logFile -Encoding ascii -Append }
    }

    $outputArray | Export-Csv -Path $csvFilePath -NoTypeInformation -Append
    Write-Host "Script finished execution" -ForegroundColor Red

    Hi,
    I have included list of Remote machines which requires userid and password for log in.
    when I run this script in my Local machine, it works good.
    but for remote machines, I am getting exception: "System.UnauthorizedAccessException".
    Please suggest some solution

    Reply
  5. Kevin

    Is there a way to modify the script so it lists all software on remote computers instead of specific software?
    It would also be handy if it could a numbered list of installed software

    Microsoft Office 2013: 5 installs
    Microsoft Office 2016: 20 installs
    7zip v16.01: 18 installs
    Flash Player 21.0.243: 13 installs
    Flash Player 21.0.219: 2 installs

    etc..

    Cheers!

    Reply
  6. Gordon

    Hi,

    Your script works great, however I am getting this at the end..

    Export-Csv : A parameter cannot be found that matches parameter name ‘Append’.
    At D:\newps.ps1:62 char:72
    + $outputArray | Export-Csv -Path $csvFilePath -NoTypeInformation -Append <<<<
    + CategoryInfo : InvalidArgument: (:) [Export-Csv], ParentContain
    sErrorRecordException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm
    ands.ExportCsvCommand

    Can you help?

    Reply
  7. George

    Anyway that this script can be modified to read all Win32_product from wmi-object or the SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ key from the registry. Like to pull the system name, product, display version, installdate and uninstallstring. I manged to do this with a vbscript, trying to learn how with powershell.

    Reply
    1. admin Post author

      This would be the script you could use instead of VBScript:

      Function Check-RemoteRegisty($ComputerName){
      Write-Host "Checking connection and registry for $ComputerName " -ForegroundColor Green
                  try{
                      $ErrorActionPreference = "STOP"
                      If(Test-Connection -ComputerName $ComputerName -count 1 -quiet){
                          try{
                             (Get-WmiObject -computerName $ComputerName Win32_Service -Filter "Name='RemoteRegistry'" -ErrorAction Stop).StartService() | Out-Null
                          }
                          catch{
                             Write-Host "Error starting remote regisry: $($_.Exception.GetType().FullName) - $($_.Exception.Message)"
                             return $_.Exception.GetType().FullName
                          }
                     }
                     Else{
                                 return "No Ping Result"
                             }
                  }
                  catch{
                       Write-Host "Error: $($_.Exception.GetType().FullName) - $($_.Exception.Message)"
                       return $_.Exception.GetType().FullName
                  }
       
        Start-Sleep -Seconds 1
      }
       
      Function Get-RemoteProgram {
      <#
      .Synopsis
      Generates a list of installed programs on a computer
       
      .DESCRIPTION
      This function generates a list by querying the registry and returning the installed programs of a local or remote computer.
       
      .NOTES  
      Name: Get-RemoteProgram
      Author: Jaap Brasser
      Version: 1.2.1
      DateCreated: 2013-08-23
      DateUpdated: 2015-02-28
      Blog: http://www.jaapbrasser.com
       
      .LINK
      http://www.jaapbrasser.com
       
      .EXAMPLE
      Get-RemoteProgram -ComputerName Server01 -Property DisplayVersion,VersionMajor
       
      .EXAMPLE
      'server01','server02' | Get-RemoteProgram -Property Uninstallstring
       
      #>
          [CmdletBinding(SupportsShouldProcess=$true)]
          param(
              [Parameter(ValueFromPipeline=$true,
                  ValueFromPipelineByPropertyName=$true,
                  Position=0)]
              [string[]]
                  $ComputerName = $env:COMPUTERNAME,
              [Parameter(Position=0)]
              [string[]]$Property
          )
       
          begin {
              $RegistryLocation = @('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\',
                                  'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\')
              $HashProperty = @{}
              $SelectProperty = @('ProgramName','ComputerName')
              if ($Property) {
                  $SelectProperty += $Property
              }
          }
       
          process {
              foreach ($Computer in $ComputerName) {
                  Check-RemoteRegisty -ComputerName $Computer | Out-Null
                  try{
                      $ErrorActionPreference = "STOP"
                      $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer)
                      foreach ($CurrentReg in $RegistryLocation) {
                          if ($RegBase) {
                          $CurrentRegKey = $RegBase.OpenSubKey($CurrentReg)
                              if ($CurrentRegKey) {
                              $CurrentRegKey.GetSubKeyNames() | ForEach-Object {
                                  if ($Property) {
                                      foreach ($CurrentProperty in $Property) {
                                          $HashProperty.$CurrentProperty = ($RegBase.OpenSubKey("$CurrentReg$_")).GetValue($CurrentProperty)
                                      }
                                  }
                                  $HashProperty.ComputerName = $Computer
                                  $HashProperty.ProgramName = ($DisplayName = ($RegBase.OpenSubKey("$CurrentReg$_")).GetValue('DisplayName'))
                                  if ($DisplayName) {
                                      New-Object -TypeName PSCustomObject -Property $HashProperty |
                                      Select-Object -Property $SelectProperty
                                  }
                              }
                          }
                      }
                  }
                }
                catch{
                      Write-Host "Error oppening registry: $($_.Exception.GetType().FullName) - $($_.Exception.Message)"
                      return $_.Exception.GetType().FullName
                }
              } # End of foreach
          }
          end{
              Write-Host "Script finished execution $($Computer)" -ForegroundColor Yellow
              }
      }
      Import-Module ActiveDirectory
       
      Get-ADComputer -Filter 'Name -like "PcName-10*"' |
      Select-Object -ExpandProperty Name |
      ForEach-Object {Get-RemoteProgram  -ComputerName $_ -Property Uninstallstring |
      Out-GridView}
      
      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *