locked
powershell script to get list of softwares installed as shown in registry on all the remote systems in a txt file RRS feed

  • Question

  • Hi

    I need to know the command for getting list of softwares installed on all the remote systems in network  which are existing in their respective registry like HKEY_LOCAL_MACHINE\SOFTWARE of all other systems
    Tuesday, March 2, 2010 6:13 AM

Answers

  • Hi.

    Here are 2 functions that you might find helpful. first one gets software through WMI
    and second one gets Software through Registry.

    Hope you find them useful.

    Regards

    Niklas

    function Get-InstalledApplicationsWMI ([string]$ComputerName) {

      Write-Host "Gathering information about installed applications on $ComputerName"

      $Product = gwmi Win32_Product -ComputerName $ComputerName

      $Product | foreach {

        if ($_.HelpLink -eq $null) {
          if($_.URLInfoAbout -eq $null) { $Documentation = $null
          } else { $Documentation = $_.URLInfoAbout }
        } else {$Documentation = $_.HelpLink}

        $ProductObject = New-Object PsObject

        $ProductObject | Add-Member NoteProperty "Application Name" -value $_.Name
        $ProductObject | Add-Member NoteProperty "System" -value $System
        $ProductObject | Add-Member NoteProperty "Vendor" -value $_.Vendor
        $ProductObject | Add-Member NoteProperty "Version" -value $_.Version
        $ProductObject | Add-Member NoteProperty "Owner" -value $_.RegOwner
        $ProductObject | Add-Member NoteProperty "Company" -value $_.RegCompany
        $ProductObject | Add-Member NoteProperty "RegOwner" -value $_.RegOwner
        $ProductObject | Add-Member NoteProperty "PackageName" -value $_.PackageName
        $ProductObject | Add-Member NoteProperty "Documentation" -value $Documentation

        return $ProductObject
      }
    }

    function Get-InstalledAppReg ([string]$ComputerName) {

      $RegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
      $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName)
      $OpenSubKey = $BaseKey.OpenSubKey($RegPath)

      $OpenSubKey.GetSubKeyNames() | ForEach {
        $Path = "$RegPath\$_"
        $BaseKey.OpenSubKey($Path).GetValue("DisplayName")
      }
    }


    Niklas Goude Blog: www.powershell.nu Twitter: @Ngoude
    Tuesday, March 2, 2010 10:09 AM
  • Codefix.

    The first post by Niklas is a function. 

    To get a list of computers into there you just need a source, either a CSV file or input from an Active Directory query.

    Presuming a CSV file with the following content in Verbatim

    NAME
    SYSTEM1
    SYSTEM2
    SYSTEM3
    SOMEOTHERSYSTEM

    and calling the CSV file Computerlist.csv

    Your script with Niklas function would look like this...........

    function Get-InstalledAppReg ([string]$ComputerName) {

      $RegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
      $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName)
      $OpenSubKey = $BaseKey.OpenSubKey($RegPath)

      $OpenSubKey.GetSubKeyNames() | ForEach {
        $Path = "$RegPath\$_"
        $BaseKey.OpenSubKey($Path).GetValue("DisplayName")
      }
    }

    $LIST=IMPORT-CSV C:\Computerlist.csv

    FOREACH ($ITEM in $LIST) {
    Get-InstalledAppReg ($ITEM)
    }

    That's it.  And the list in the Registry is actually more accurate than the WMI, I believe Hotfixes are stored in that same location.

    Sean
    The Energized Tech


    Powershell. It's so Easy and it's FREE! Dive in and use it now, It'll take no time. :) http://www.energizedtech.com http://www.itprotoronto.ca
    • Marked as answer by IamMred Thursday, March 4, 2010 8:04 PM
    Wednesday, March 3, 2010 8:59 PM

All replies

  • Hi.

    Here are 2 functions that you might find helpful. first one gets software through WMI
    and second one gets Software through Registry.

    Hope you find them useful.

    Regards

    Niklas

    function Get-InstalledApplicationsWMI ([string]$ComputerName) {

      Write-Host "Gathering information about installed applications on $ComputerName"

      $Product = gwmi Win32_Product -ComputerName $ComputerName

      $Product | foreach {

        if ($_.HelpLink -eq $null) {
          if($_.URLInfoAbout -eq $null) { $Documentation = $null
          } else { $Documentation = $_.URLInfoAbout }
        } else {$Documentation = $_.HelpLink}

        $ProductObject = New-Object PsObject

        $ProductObject | Add-Member NoteProperty "Application Name" -value $_.Name
        $ProductObject | Add-Member NoteProperty "System" -value $System
        $ProductObject | Add-Member NoteProperty "Vendor" -value $_.Vendor
        $ProductObject | Add-Member NoteProperty "Version" -value $_.Version
        $ProductObject | Add-Member NoteProperty "Owner" -value $_.RegOwner
        $ProductObject | Add-Member NoteProperty "Company" -value $_.RegCompany
        $ProductObject | Add-Member NoteProperty "RegOwner" -value $_.RegOwner
        $ProductObject | Add-Member NoteProperty "PackageName" -value $_.PackageName
        $ProductObject | Add-Member NoteProperty "Documentation" -value $Documentation

        return $ProductObject
      }
    }

    function Get-InstalledAppReg ([string]$ComputerName) {

      $RegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
      $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName)
      $OpenSubKey = $BaseKey.OpenSubKey($RegPath)

      $OpenSubKey.GetSubKeyNames() | ForEach {
        $Path = "$RegPath\$_"
        $BaseKey.OpenSubKey($Path).GetValue("DisplayName")
      }
    }


    Niklas Goude Blog: www.powershell.nu Twitter: @Ngoude
    Tuesday, March 2, 2010 10:09 AM
  • Hey

    Sorry this isn't powershell but it should do the job if you want to use it. The problem with using the Win32_Product WMI Class to enumerate the installed software (especially on Windows 2000 & 2003 Servers) is that the WMI class is NOT installed by default. Here is a VBScript i wrote to read a list of hostnames from a text file named "ComputerNames.txt" from the scripts directory and attempt to remotely enumerate all subkeys within the following registry key

    HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall

    For each subkey enumerated it will attempt to read the value of the "DisplayName" key and output the results to a csv file.

    (the results should be the same as what you would see when you open Add/Remove Programs)

    Hope that helps

    Cheers

    Matt :)

    '----------------------------------------------------------------------------------------------------------------------------
    'Script Name : CheckInstalledSoftware.vbs
    'Author      : Matthew Beattie
    'Created     : 01/03/10
    'Description : This script reads a list of hostnames from a text file name "ComputerNames.txt" in the scripts working 
    '            : directory. For each hostName it requests an ICMP response and if successfull attempts a remote registry
    '            : connection to enumerate and read the registry values of installed software. All results are logged to the
    '            : scripts working directory in a log file per computer name.
    '----------------------------------------------------------------------------------------------------------------------------
    'Initialization  Section
    '----------------------------------------------------------------------------------------------------------------------------
    Option Explicit
    Const ForReading   = 1
    Const ForAppending = 8
    Dim objFSO, wshNetwork, wshShell, hostName
    Dim scriptBaseName, scriptPath, scriptLogPath
    On Error Resume Next
       Set objFSO     = CreateObject("Scripting.FileSystemObject")
       Set wshShell   = CreateObject("WScript.Shell")
       Set wshNetwork = CreateObject("WScript.Network")
       scriptBaseName = objFSO.GetBaseName(Wscript.ScriptFullName)
       scriptPath     = objFSO.GetFile(Wscript.ScriptFullName).ParentFolder.Path
       scriptLogPath  = scriptPath & "\" & IsoDateString(Now)
       If Err.Number <> 0 Then
          Wscript.Quit
       End If
    On Error Goto 0
    '----------------------------------------------------------------------------------------------------------------------------
    'Main Processing Section
    '----------------------------------------------------------------------------------------------------------------------------
    On Error Resume Next
       PromptStart
       ProcessScript
       If Err.Number <> 0 Then
          Wscript.Quit
       End If
       PromptEnd
    On Error Goto 0
    '----------------------------------------------------------------------------------------------------------------------------
    'Functions Processing Section
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : ProcessScript -> Primary Function that controls all other script processing.
    'Parameters : None          ->
    'Return     : None          ->
    '----------------------------------------------------------------------------------------------------------------------------
    Function ProcessScript
       Dim fileSpec, hostNames, regKey, keyName, results, result
       keyName   = "DisplayName"
       regKey    = "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
       fileSpec  = scriptPath & "\ComputerNames.txt"
       '-------------------------------------------------------------------------------------------------------------------------
       'Ensure the "ComputerNames.txt" file exists within the scripts working directory.
       '-------------------------------------------------------------------------------------------------------------------------
       If Not objFSO.FileExists(fileSpec) Then
          MsgBox DQ(fileSpec) & " does not exist!", vbCritical, scriptBaseName
          Exit Function
       End If
       '-------------------------------------------------------------------------------------------------------------------------
       'Read the list of hostNames from the "ComputerNames.txt" text file within the scripts working directory.
       '-------------------------------------------------------------------------------------------------------------------------
       If Not GetScriptInput(hostNames, fileSpec) Then
          Exit Function
       End If
       '-------------------------------------------------------------------------------------------------------------------------
       'Attempt to read the registry from each hostname read from the list of hostnames.
       '-------------------------------------------------------------------------------------------------------------------------
       For Each hostName In hostNames
          Do
             '-------------------------------------------------------------------------------------------------------------------
             'Ensure the system responds to an ICMP request.
             '-------------------------------------------------------------------------------------------------------------------
             If Not CheckConnection(hostName) Then
                LogMessage 2, "Failed to respond to an ICMP Request"
                Exit Do
             End If
             '-------------------------------------------------------------------------------------------------------------------
             'Enumerate and read the registry values.
             '-------------------------------------------------------------------------------------------------------------------
             If Not GetRegValues(results, hostName, keyName, regKey) Then
                Exit Do
             End If
             '-------------------------------------------------------------------------------------------------------------------
             'Log the registry values results.
             '-------------------------------------------------------------------------------------------------------------------
             For Each result In results
                LogMessage 0, result
             Next
          Loop Until True
       Next
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : GetScriptInput -> Reads a text file to be used as Script input.
    'Parameters : items          -> Output: An array of items in the script input file.
    '           : fileSpec       -> The full folder Path, file Name and extention of the script input file.
    'Return     : GetScriptInput -> Returns an array of items for script input and True or False.
    '----------------------------------------------------------------------------------------------------------------------------
    Function GetScriptInput(items, fileSpec)
       Dim scriptInputFile, itemsDict, item
       GetScriptInput = False
       Set itemsDict  = NewDictionary
       If Not objFSO.FileExists(fileSpec) Then
          Exit Function
       End If
       On Error Resume Next
          Set scriptInputFile = objFSO.OpenTextFile(fileSpec, ForReading)
          If Err.Number <> 0 Then
             Exit Function
          End If
       On Error Goto 0
       Do Until scriptInputFile.AtEndOfStream
          item = scriptInputFile.ReadLine
          If item = "" Then
             Exit Function         
          End If
          If Not itemsDict.Exists(item) Then
             itemsDict.Add item, ""
          End If
       Loop
       items          = itemsDict.Keys
       GetScriptInput = True
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : CheckConnection -> Checks a remote host using WMI ping.
    'Parameters : hostName        -> Hostname of computer system to verify network connectivity with.
    'Return     : Boolean         -> True if hostname replies. False otherwise.
    '----------------------------------------------------------------------------------------------------------------------------
    Function CheckConnection(hostName)
       Dim ping, response, replied
       Set ping = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
                           ("select * from Win32_PingStatus where address = '" & hostName & "'")
       For each response in ping
          replied = Not IsNull(response.StatusCode) And response.StatusCode = 0
       Next
       CheckConnection = replied
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : GetRegValues -> Enumerates the subkeys in a registry key and the values of the keyName.
    'Parameters : hostName     -> String containing the hostName of the system to enumerate the registry keys on.
    '           : keyName      -> String containing the name of the registry key value to enumerate.
    '           : regKey       -> Registry key to enumerate subkey names for.
    'Return     : GetRegValues -> Returns True and an Array containing the registry key values otherwise False.
    '----------------------------------------------------------------------------------------------------------------------------
    Function GetRegValues(results, hostName, keyName, regKey)
       Dim objReg, regDict, rootKey, hive, keyValue, subKeys, i
       GetRegValues = False
       rootKey      = regKey
       hive         = GetRegistryHiveFromKey(rootKey)
       On Error Resume Next
          If hive <> 0 Then
             '-------------------------------------------------------------------------------------------------------------------
             'Create a dictionary object to store the registry values in.
             '-------------------------------------------------------------------------------------------------------------------
             Set regDict = NewDictionary
             If Err.Number <> 0 Then
                LogMessage 1, "Creating Dictionary Object"
                Exit Function
             End If
             '-------------------------------------------------------------------------------------------------------------------
             'Connect to the remote registry.
             '-------------------------------------------------------------------------------------------------------------------
             Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & hostName & "\root\default:StdRegProv")
             If Err.Number <> 0 Then
                LogMessage 1, "Creating StdRegProv Object"
                Exit Function
             End If
             '-------------------------------------------------------------------------------------------------------------------
             'Enumerate the subkey names within the regKey paramater.
             '-------------------------------------------------------------------------------------------------------------------
             objReg.EnumKey hive, rootKey, subKeys
             If Err.Number <> 0 Then
                LogMessage 1, "Enumerating Registry Keys"
                Exit Function
             End If
             '-------------------------------------------------------------------------------------------------------------------
             'Ensure the results are an array.
             '-------------------------------------------------------------------------------------------------------------------
             If Not IsArray(subKeys) Then
                subKeys = Array(subKeys)
             End If
             '-------------------------------------------------------------------------------------------------------------------
             'Read the registry key value for each subkey. Add the results to the dictionary.
             '-------------------------------------------------------------------------------------------------------------------
             For i = 0 to UBound(subKeys)
                objReg.GetStringValue hive, rootKey & "\" & subKeys(i), keyName, keyValue
                If Err.Number = 0 Then
                   If Not IsNull(keyValue) Then
                      regDict(regDict.Count) = keyValue
                   End If
                Else
                   Err.Clear
                End If
             Next
          End If
       On Error Goto 0
       results      = regDict.Items
       GetRegValues = True
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name      : GetRegistryHiveFromKey -> Get the hive ID from a registry key name.
    'Parameters: Input/Output: key      -> Registry key name. Hive name will be removed.
    'Return    : GetRegistryHiveFromKey -> ID of hive of given key name (0 if invalid).
    '          :                        -> The hive name is removed from the input key name.
    '----------------------------------------------------------------------------------------------------------------------------
    Function GetRegistryHiveFromKey (key)
       Dim pos, hive
       pos = Instr (key, "\")
       If pos = 0 Then
          pos = Len(key) + 1
       End If
       hive = Left (UCase (Left (key, pos - 1)) & " ", 4)
       key  =              Mid  (key, pos + 1)
       GetRegistryHiveFromKey = Array(0, &H80000000, &H80000001, &H80000002, &H80000003, &H80000005, &H80000006) _
                                     (Int ((Instr("HKCR,HKCU,HKLM,HKU ,HKCC,HKDD", hive) + 4) / 5))
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : NewDictionary -> Creates a new dictionary object.
    'Parameters : None          ->
    'Return     : NewDictionary -> Returns a dictionary object.
    '----------------------------------------------------------------------------------------------------------------------------
    Function NewDictionary
       Dim dict
       Set dict          = CreateObject("scripting.Dictionary")
       dict.CompareMode  = vbTextCompare
       Set NewDictionary = dict
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : DQ          -> Place double quotes around a string and replace double quotes
    '           :             -> within the string with pairs of double quotes.
    'Parameters : stringValue -> String value to be double quoted
    'Return     : DQ          -> Double quoted string.
    '----------------------------------------------------------------------------------------------------------------------------
    Function DQ (ByVal stringValue)
       If stringValue <> "" Then
          DQ = """" & Replace (stringValue, """", """""") & """"
       Else
          DQ = """"""
       End If
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : IsoDateTimeString -> Generate an ISO date and time string from a date/time value.
    'Parameters : dateValue         -> Input date/time value.
    'Return     : IsoDateTimeString -> Date and time parts of the input value in "yyyy-mm-dd hh:mm:ss" format.
    '----------------------------------------------------------------------------------------------------------------------------
    Function IsoDateTimeString(dateValue)
       IsoDateTimeString = IsoDateString (dateValue) & " " & IsoTimeString (dateValue)
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : IsoDateString -> Generate an ISO date string from a date/time value.
    'Parameters : dateValue     -> Input date/time value.
    'Return     : IsoDateString -> Date part of the input value in "yyyy-mm-dd" format.
    '----------------------------------------------------------------------------------------------------------------------------
    Function IsoDateString(dateValue)
       If IsDate(dateValue) Then
          IsoDateString = Right ("000" &  Year (dateValue), 4) & "-" & _
                          Right (  "0" & Month (dateValue), 2) & "-" & _
                          Right (  "0" &   Day (dateValue), 2)
       Else
          IsoDateString = "0000-00-00"
       End If
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : IsoTimeString -> Generate an ISO time string from a date/time value.
    'Parameters : dateValue     -> Input date/time value.
    'Return     : IsoTimeString -> Time part of the input value in "hh:mm:ss" format.
    '----------------------------------------------------------------------------------------------------------------------------
    Function IsoTimeString(dateValue)
       If IsDate(dateValue) Then
          IsoTimeString = Right ("0" &   Hour (dateValue), 2) & ":" & _
                          Right ("0" & Minute (dateValue), 2) & ":" & _
                          Right ("0" & Second (dateValue), 2)
       Else
          IsoTimeString = "00:00:00"
       End If
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : LogMessage  -> Parses a message to the log file based on the messageType.   
    'Parameters : messageType -> Integer representing the messageType.
    '           :             -> 0 = message       (writes to a ".csv" file)
    '           :             -> 1 = error,        (writes to a ".err" file including information relating to the error object.)
    '           :             -> 2 = error message (writes to a ".err" file without information relating to the error object.)
    '           : message     -> String containing the message to write to the log file.
    'Return     : None        -> 
    '----------------------------------------------------------------------------------------------------------------------------
    Function LogMessage(messageType, message)
       Dim prefix, logType
       prefix = hostName
       Select Case messageType
          Case 0
             logType = "csv"
          Case 1
             logType = "err"
             message = "Error " & Err.Number & " (Hex " & Hex(Err.Number) & ") " & message & ". " & Err.Description
          Case Else
             LogType = "err"
       End Select
       If Not LogToCentralFile(scriptLogPath & "." & logType, hostName & "," & message) Then  
          Exit Function  
       End If
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : LogToCentralFile -> Attempts to Appends information to a central file.
    'Parameters : logSpec          -> Folder path, file name and extension of the central log file to append to.
    '           : message          -> String to include in the central log file
    'Return     : LogToCentralFile -> Returns True if Successfull otherwise False.
    '----------------------------------------------------------------------------------------------------------------------------
    Function LogToCentralFile(logSpec, message)
       Dim attempts, objLogFile
       LogToCentralFile = False
       '-------------------------------------------------------------------------------------------------------------------------
       'Attempt to append to the central log file up to 10 times, as it may be locked by some other system.
       '-------------------------------------------------------------------------------------------------------------------------
       attempts = 0
       On Error Resume Next
          Do
             Set objLogFile = objFSO.OpenTextFile(logSpec, ForAppending, True)
             If Err.Number = 0 Then
                objLogFile.WriteLine message
                objLogFile.Close
                LogToCentralFile = True
                Exit Function
             End If
             Randomize
             Wscript.sleep 1000 + Rnd * 100
             attempts = attempts + 1
          Loop Until attempts >= 10
       On Error Goto 0
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : PromptStart -> Prompt when script starts.
    'Parameters : None        ->
    'Return     : None        ->
    '----------------------------------------------------------------------------------------------------------------------------
    Function PromptStart
       MsgBox "Now processing the " & DQ(Wscript.ScriptName) & " script.", vbInformation, scriptBaseName
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : PromptEnd -> Prompts when script has completed.
    'Parameters : None      ->
    'Return     : None      ->
    '----------------------------------------------------------------------------------------------------------------------------
    Function PromptEnd
       MsgBox "The " & DQ(Wscript.ScriptName) & " script has completed successfully.", vbInformation, scriptBaseName
    End Function
    '----------------------------------------------------------------------------------------------------------------------------
    'Name       : PromptError -> Prompts when an unexpected script error occurs.
    'Parameters : None        ->
    'Return     : None        ->
    '----------------------------------------------------------------------------------------------------------------------------
    'Function PromptEnd
    '   MsgBox "Error " & Err.Number & " (Hex " & Hex(Err.Number) & "). " & Err.Description, vbCritical, scriptBaseName
    'End Function
    '----------------------------------------------------------------------------------------------------------------------------
    Tuesday, March 2, 2010 11:15 AM
  • I wrote a blog post on remotly enabling the Win32_product class on Server 2003 via PowerShell.
    http://unlockpowershell.wordpress.com/2010/02/13/remotely-install-win32_product-class-on-server-2003/

    Karl
    http://unlockpowershell.wordpress.com
    Tuesday, March 2, 2010 3:04 PM
  • Thanks a lot niklas but just want to clarify how it will take a list of computers from a txt file ...
    Wednesday, March 3, 2010 6:09 AM
  • Thank you very much matthew but iam particularly looking for powershell..I appreciate your help thanks again..
    Wednesday, March 3, 2010 7:23 AM
  • Codefix.

    The first post by Niklas is a function. 

    To get a list of computers into there you just need a source, either a CSV file or input from an Active Directory query.

    Presuming a CSV file with the following content in Verbatim

    NAME
    SYSTEM1
    SYSTEM2
    SYSTEM3
    SOMEOTHERSYSTEM

    and calling the CSV file Computerlist.csv

    Your script with Niklas function would look like this...........

    function Get-InstalledAppReg ([string]$ComputerName) {

      $RegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
      $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName)
      $OpenSubKey = $BaseKey.OpenSubKey($RegPath)

      $OpenSubKey.GetSubKeyNames() | ForEach {
        $Path = "$RegPath\$_"
        $BaseKey.OpenSubKey($Path).GetValue("DisplayName")
      }
    }

    $LIST=IMPORT-CSV C:\Computerlist.csv

    FOREACH ($ITEM in $LIST) {
    Get-InstalledAppReg ($ITEM)
    }

    That's it.  And the list in the Registry is actually more accurate than the WMI, I believe Hotfixes are stored in that same location.

    Sean
    The Energized Tech


    Powershell. It's so Easy and it's FREE! Dive in and use it now, It'll take no time. :) http://www.energizedtech.com http://www.itprotoronto.ca
    • Marked as answer by IamMred Thursday, March 4, 2010 8:04 PM
    Wednesday, March 3, 2010 8:59 PM
  • Thanks Sean well its getting the data computers in the list but I want the ouput of all the computers in the Txt to an csv or excel file when i gave filename.ps1 << registry.csv it throws an error as The '<' operator is reserved for future use.
    At line:1 char:21
    + .\registrysoft.ps1 < <<<< registry.xls
        + CategoryInfo          : ParserError: (<:OperatorToken) [], ParentContain
       sErrorRecordException
        + FullyQualifiedErrorId : RedirectionNotSupported REDIRECTION NOT SUPPORTED any clue?
    Friday, March 5, 2010 9:16 AM
  • << is not supported for redirecting, use >> instead or use the Out-File cmdlet with the -append switch parameter.
    example:

    $MyFile = "C:\Temp\MyFile.txt"

    "Some Text" >> $MyFile

    or

    "Some other text" | Out-File $MyFile -Append


    Niklas Goude Blog: www.powershell.nu Twitter: @Ngoude
    Sunday, March 7, 2010 9:56 PM
  • Thanks Niklas...
    Wednesday, March 10, 2010 6:51 AM
  • Getting software via WMI while much more precise is VERY time intensive as well as disk intensive on the target machine, especially when the installed software count is very very high. The WMI call triggers msiexec which logs an entry in your app log for each item found, so it can be pretty rough on the remote machine. I like the registry approach as its WAY faster on the same machine, the only problem is that on 64bit windows, i'm missing a fair number of applications. I tried using the HKLM:\SOFTWARE\WoW6432Node\Microsoft\Windows\Current Version\Uninstall but that appears to mirror the 32bit key.

    How do i enum the 64bit installed applications on my system via the registry?

    Thanks,


    Jeffrey S. Patton Assistant Director of IT School of Engineering Computing Services University of Kansas 1520 West 15th Street Lawrence, KS. 66045-7621 | http://patton-tech.com
    Friday, July 1, 2011 7:28 PM
  • I have never had a problem. I have used it repeatedly on large systems with many user active and have not seen any issuses. There are bugs or deficiencies in older version of teh installer that can cause things to slow down. The latest installers, post 3.0, do not seem to slow things down. I usually start this up inpowershell and let it spawn jobe thengo to lunch or dinner and its done when I retrun. I so monthly version checks on multiple customer sites to be sure Adobe, QB Jav and other software packages are updates.
    jv
    Friday, July 1, 2011 8:23 PM
  • Looks like a combination of a few registry keys may be needed.  

    These two are different lists:

    HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\

    HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\

    I'm writing a script to detect a specific program and couldn't find it in the first list, but it was in the second one.  There are probably a few other locations.  I'd like to know what populates "Programs and Features"...

    • Edited by Eddy Collins Friday, September 28, 2012 11:59 PM
    Friday, September 28, 2012 11:55 PM
  • Eddy - this topic has been closed for years. Please start a new topic with your questions.

    Look in the repository as there ar at least three scripts that do what you want in 32 and 64 bit environments.


    ¯\_(ツ)_/¯

    Saturday, September 29, 2012 4:05 AM
  • I realize that this is an old thread, but I have discovered some information that may be useful:

    In Niklas' original function for finding installed applications in the registry, he has it searching thru HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall for registered installed programs.  It is worth noting that on 64-bit machines, there is also Uninstall information at HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall.  Depending on the program, it may only be listed in the Wow6432Node registry.  My simple update of the function looks like this:

    function Get-InstalledAppReg ([string]$ComputerName) {
    
      $RegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
      $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName)
      $OpenSubKey = $BaseKey.OpenSubKey($RegPath)
    
      $OpenSubKey.GetSubKeyNames() | ForEach {
        $Path = "$RegPath\$_"
        $BaseKey.OpenSubKey($Path).GetValue("DisplayName")
      }
    
      $RegPath = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
      $OpenSubKey = $BaseKey.OpenSubKey($RegPath)
    
      $OpenSubKey.GetSubKeyNames() | ForEach {
        $Path = "$RegPath\$_"
        $BaseKey.OpenSubKey($Path).GetValue("DisplayName")
      }
    
    }

    Hope this helps.

    Eric

    Wednesday, February 19, 2014 7:26 PM
  • Hi,

    Possibly a more flexible and easier to use alternative is here:

    Windows IT Pro: Auditing 32-Bit and 64-Bit Applications with PowerShell

    Bill

    Wednesday, February 19, 2014 8:04 PM