It can be difficult to know what applications are installed on the machines in any given company. Not knowing what is installed where, can lead to all kinds of trouble when updates are pushed and changes are made. Enterprise class tools like System Center that can create a CMDB are expensive. So what’s an Admin supposed to do?

If your budget won’t allow you to purchase a tool or pay a DEV team to write you one; you’ll have to do it yourself. PowerShell is always my goto tool for this kind of thing on a Windows network. You could accomplish the same goal with VBS or even CMD batch files, but if you are running systems so old that you have to resort to those tools, you have bigger problems than worrying about what apps are installed.

If you’ve spent time researching this, you’ve probably seen several techniques to get the data that you’re after. I like connecting to the registry and searching the 32 bit and 64 bit uninstall keys because it is fast, accurate, and has a lot of info available. You could also use WMI/CMI, scan the Program Files directories for exe files, and more. As with everything in any kind of programming; the hard part isn’t getting the data, it’s out-putting it into something useable. Lucky for you I’ve included that feature in my script.

The code below will locate your AD Forests and find domain controllers in each of them. Next it will scan for objects that contain “Windows Server” in the Operating System description and add those object’s DNS host names to an array. It will ping each server in that array to see if they are real and on-line, because AD can have dead objects in it. Then it will add the systems that are up to another array and for each of those, the script will remotely access the registry keys that contain the uninstall data. The uninstall data will be used to create a CSV report that lists each application’s name, version, help link, and install date along with the name of the machine.

Import-Module ActiveDirectory
$domains = (Get-ADForest).domains
$dcs = Foreach ($domain in $domains) {Get-ADDomainController -DomainName $domain -Discover -Service PrimaryDC}
$servers = Foreach ($dc in $dcs) {
Get-ADComputer -Properties * -Filter {(OperatingSystem -like "*Windows Server*")}|Select DNSHostName -ExpandProperty DNSHostName

Foreach ($server in $servers){
$PingTest = Test-Connection -ComputerName $server -Count 1 -Quiet
If ($PingTest)
$servers += $server
{Write-Warning "Failed to connect to server '$Server'."}

$report = @()
ForEach ($server in $servers) {
$report += Invoke-Command -ComputerName $server -Command {Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object @{n="Application"; e={$_.DisplayName}}, @{n="Version"; e={$_.DisplayVersion}}, HelpLink, Publisher, InstallDate | Sort-Object Application}

$report | Format-Table -AutoSize
$report |select -Property * -ExcludeProperty RunspaceID, PSShowComputerName|Export-Csv -Path $env:userprofile\documents\windows_servers_cmdb.csv -NoTypeInformation

You’ll need to have the RSTAT tools installed or run the application from a Server that has them. To be successful you’ll also need enough privileges to scan the remote machines registry and your network can’t be blocking WinRM. Other than that, just save the code to a PS1 file and run it. The report will be in your Documents folder named windows_servers_cmdb.csv.

If you want to adjust to scan apps on workstations just change the filter keyword to “Windows Workstation”; you could also do both. To fully automate it just add a line at the bottom to email the attachment and schedule it to run as a task. If you want to get really creative convert the table into HTML and upload it to an IIS or Apache host every day. If you have SharePoint you can upload it to a custom list and then create some pretty killer reports. Views that filter for key words like “Exchange” or “SQL” are helpful for everyone.

Be sure to tell your boss it took you all week to do this LOL.