Get Programs and Features script

I was trying to find a good method/script to (remotely) get all the installed programs from a Windows 7 client. I didn’t want to use Remote Desktop or similar however, so it had to be a method that was unnoticeable for the user. I know that SCCM has its own software inventory, but I wanted a fast(er) way to check if version XXX of Office is installed on a client. The reason for this was mainly because there are (unfortunately) soooo many different Office installations throughout the whole University. (Also, it’s nice to have some clues about the client before SCCM starts using its magic). The script lists more than (Office) installations however, including other useful information as well. It is based on

https://community.spiceworks.com/scripts/show/2170-get-a-list-of-installed-software-from-a-remote-computer-fast-as-lightning.

and It basically queries the registry of a remote client and returns the installed software. Cheers to the author Anthony Howell!

This modified version also lists:

  • Colored headings 🙂
  • OS Name
  • OS Version
  • System Model
  • Total Physical Memory
  • Original Install Date
  • Uptime/System Boot Time
  • Current logged on user

Usage: .\get_programs_and_features.ps1 computername.

Here’s a screenshot with example output:

programsandfeaturesscript

Fig 1. get_programs_and_features.ps1

 

The text in the screenshot is in Swedish, but it should be quite self explanatory 🙂

If you want to have a go yourself, the script looks like this (download link at the bottom):

Param
    (
        [Alias(‘Computer’,’ComputerName’,’HostName’)]
        [Parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true,Position=1)]
        [string[]]$Name = $env:COMPUTERNAME
    )
    Begin
    {
        $LMkeys = “Software\Microsoft\Windows\CurrentVersion\Uninstall”,”SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall”
        $LMtype = [Microsoft.Win32.RegistryHive]::LocalMachine
        $CUkeys = “Software\Microsoft\Windows\CurrentVersion\Uninstall”
        $CUtype = [Microsoft.Win32.RegistryHive]::CurrentUser
       
    }
    Process
    {
        ForEach($Computer in $Name)
        {
            “”
            “”
            write-host “Information om datorn: ” $Computer -foreground “magenta”
            “”
            $datastring= systeminfo /s $Computer
            $datastring | find “OS Name”
            $datastring | find “OS Version”
            $datastring | find “System Model”           
            $datastring | find “Total Physical Memory”
            “”
            $datastring | find “Original Install Date”           
            $datastring | find “System Boot Time”
            “”
            “”
            write-host “Inloggad person för tillfället (console): ” -foreground “magenta”
            “”
            qwinsta /server:$Computer
            “”
            “”
            $MasterKeys = @()
            If(!(Test-Connection -ComputerName $Computer -count 1 -quiet))
            {
                Write-Error -Message “Unable to contact $Computer. Please verify its network connectivity and try again.” -Category ObjectNotFound -TargetObject $Computer
                Break
            }
            $CURegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($CUtype,$computer)
            $LMRegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($LMtype,$computer)
            ForEach($Key in $LMkeys)
            {
                $RegKey = $LMRegKey.OpenSubkey($key)
                If($RegKey -ne $null)
                {
                    ForEach($subName in $RegKey.getsubkeynames())
                    {
                        foreach($sub in $RegKey.opensubkey($subName))
                        {
                            $MasterKeys += (New-Object PSObject -Property @{
                            “ComputerName” = $Computer
                            “Name” = $sub.getvalue(“displayname”)
                            “SystemComponent” = $sub.getvalue(“systemcomponent”)
                            “ParentKeyName” = $sub.getvalue(“parentkeyname”)
                            “Version” = $sub.getvalue(“DisplayVersion”)
                            “UninstallCommand” = $sub.getvalue(“UninstallString”)
                            })
                        }
                    }
                }
            }
            ForEach($Key in $CUKeys)
            {
                $RegKey = $CURegKey.OpenSubkey($Key)
                If($RegKey -ne $null)
                {
                    ForEach($subName in $RegKey.getsubkeynames())
                    {
                        foreach($sub in $RegKey.opensubkey($subName))
                        {
                            $MasterKeys += (New-Object PSObject -Property @{
                            “ComputerName” = $Computer
                            “Name” = $sub.getvalue(“displayname”)
                            “SystemComponent” = $sub.getvalue(“systemcomponent”)
                            “ParentKeyName” = $sub.getvalue(“parentkeyname”)
                            “Version” = $sub.getvalue(“DisplayVersion”)
                            “UninstallCommand” = $sub.getvalue(“UninstallString”)
                            })
                        }
                    }
                }
            }
            $MasterKeys = ($MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne “1” -AND $_.ParentKeyName -eq $Null} | select Name,Version | sort Name)
            “”
            write-host “Har följande program installerade:” -foreground “magenta”
            $MasterKeys
        }
    }
    End
    {
       
    }

 

Downloadable version (translated to English): get_programs_and_features.zip

Advertisements

2 thoughts on “Get Programs and Features script

  1. Morjens,
    Brukar läsa din blogg och måste säga att du ska fortsätta göra ett gott arbete! Sällan stöter man på så detaljerade beskrivningar som du gör. Jag är själv en powershell-nörd och tycker powershell är det bästa som hänt på länge för Windows. Vad gäller ovanstående skript så tog det lite i ögat att läsa “write-host” eftersom självaste Jeffrey Snover rekommenderar att istället använda “write-output” eller “write-verbose”(http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/). Detta lärde jag själv för någon tid sedan och ville nu dela med mig om du inte råkade veta om denna detalj från tidigare. Som regel brukar jag kolla igenom skripts som andra har skrivit och byter ut “write-host”.

    Här är också lite att läsa angående att polla datorer över installerad softa och vad man inte ska göra: https://blogs.technet.microsoft.com/heyscriptingguy/2011/11/13/use-powershell-to-quickly-find-installed-software/ Skriptet som du använde frågar inte via WMI, men jag lägger nu detta här för giggles om du inte tidigare råkat stöta på samma artikel.

    För övrigt så “keep up the good” work!

    • Tack för kommentarerna! Jag kan genast nämna att jag i min tur INTE är en powershell-nörd (trots att det skulle vara skoj att vara det).
      Hur som, jag håller “write-output” i minnet för framtida bruk 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s