Getting a list of installed software in Windows with Puppet


  • Share on Google+

A Puppet fact to generate a list of installed programs on Windows desktops or servers.

I decided to create this Puppet fact, so that our asset management website could display a list of software installed on every workstation in our domain.

I wanted the list of software to be the same, or very close to the the list you get when opening the Programs and Features settings in Windows.

Going through uninstall keys in registry

My first approach was to loop through the uninstall keys in the registry under. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

However I quickly found out that I got way more entries that I wanted. The reason is that, the Programs and Features list Windows displays are filtered. It excludes all system components and KB updates.

Filtering out the noise

Using the win32/registry library for Ruby, I looped through the each key in Uninstall and selected only the ones with a displayname and uninstallpath. Then filtered all with systemcomponent equal to 1, and then all with a displayname that matched against this regex (/[KB]{2}\d{7}/) to filter out all Windows updates. Lastly added the displayname and version as a hash to the array.

# Loop through all uninstall keys for 64bit applications.  
Win32::Registry::HKEY_LOCAL_MACHINE.open('Software\Microsoft\Windows\CurrentVersion\Uninstall') do |reg|
    reg.each_key do |key|
            
    k = reg.open(key)
    
    displayname     = k["DisplayName"] rescue nil
    version         = k["DisplayVersion"] rescue nil      
    uninstallpath   = k["UninstallString"] rescue nil
    systemcomponent = k["SystemComponent"] rescue nil

    if(displayname && uninstallpath)
        unless(systemcomponent == 1)
          unless(displayname.match(/[KB]{2}\d{7}/)) # excludes windows updates
            software_list << {DisplayName: displayname, Version: version }
          end
        end
    end

    end
end
Getting all applications

To get all the applications I needed to loop both the 64 bit and 32 bit uninstall path plus the uninstall key for user applications.

64 bit path.
Software\Microsoft\Windows\CurrentVersion\Uninstall
32 bit path.
Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall

Finally – Displaying data

I integrated the application list into our asset manager. (built in RoR)
Fetching the software list from Puppetdb via a rest api call, and displaying the data in a datatable for easy sorting and filtering for the end user.

I tested the fact successfully on Windows 10 and Windows 7 – 64 bit. There is a issue on Windows 7 – 32 bit. I haven’t looked into what causing the problem.

The full code to the Puppet fact can be found here

  • Ben
    Reply
    Author
    Ben

    Hey Casper, thanks for the blog! I’m testing this out with Puppet 6.10.1 on Server 2019 and i get:

    Error: Facter: error while resolving custom fact “software”: U+00AE to IBM437 in conversion from UTF-16LE to UTF-8 to IBM437

    From googling around, this seems to be some sort of general issue with ruby and win32/registry. It doesn’t happen when i run irb on my local win10 machine. Ever seen this?

    • Casper Nielsen
      Reply
      Author
      Casper Nielsen

      Hi Ben, that is a very good question.

      I must admit that it’s been a while since I worked and used this Puppet fact.
      As I remember we only used this for our workstations (mix of Win 10 & 7)
      Don’t think I ever tried on a server.

      It could be the Ruby Library as you mentioned. Right now I think you know more that me on this issue.
      I don’t think I can bring any inputs on this problem right now.

      If you find a solution, please leave a comment on how to fix it. Would love to hear.