Skip to content

Instantly share code, notes, and snippets.

@bmcguirk
Created December 19, 2019 15:29
Show Gist options
  • Save bmcguirk/8214196b66e49f4833413a2649c7cc54 to your computer and use it in GitHub Desktop.
Save bmcguirk/8214196b66e49f4833413a2649c7cc54 to your computer and use it in GitHub Desktop.
Powershell script to get all the machines in a particular OU and then get all the programs installed on those machines.
# A Powershell Script to Get AD Machines from a certain OU and then query/export a CSV of their installed software inventory.
# 2019-10-17 - v1 - Author: Brian McGuirk - The Script works, but could maybe use a progress bar. Next up.
# 2019-11-14 - v2 - Author: Brian McGuirk - Added a progress bar. Limited properties to just useful ones. I think.
# Pre-requisites:
# - The Active Directory Powershell modules. In Windows 10, this should be an enable-able "Optional Feature."
# - The target machines must WMI enabled.
# Go here for more information: https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-start-page
Write-Host "Starting Inventory Script..."
# THE SCRIPT
# 1. Establish a path for the output file containing the machine names and store it in the $machine_path variable.
$machine_path="your_target_list_of_machines.txt"
# 2. Get machine names that match a particular pattern.
# Some notes:
# In this instance, we're getting all the computers that in the 'Accounting' OU.
# That's what `-Filter * -SearchBase "OU=Accounting,OU=Workstations,DC=enterprise,DC=contoso,DC=com"` is specifying.
# You should update this parameter for your desired naming convention or OU.
# Check this out for more information on filtering:
# https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adcomputer?view=win10-ps#examples
# Using the `.Name` accessor allows you to just export a flat, simple file with just the machine names.
# Pipe the output of this command to `Out-File` and provide it the `$machine_path` variable you established above.
Write-Host "Exporting machine names to: $machine_path ."
(Get-ADComputer -Filter * -SearchBase "OU=Accounting,OU=Workstations,DC=enterprise,DC=contoso,DC=com").Name | Out-File $machine_path
# 2. Invoke Get-WmiObject in the format below to gather everything in "Add/Remove Programs" in Control Panel.
# Some notes:
# - The `-ComputerName (Get-Content $machine_path)` parameter reads in the CSV you just created
# - The `ErrorAction SilentlyContinue` is designed to not raise and error and crash the script if the command can't run (because the PC is off, for example).
# - The `$installed_programs_export` variable is the path (relative or absolute) where you want to export this CSV.
# - This filename is now set up to auto-update the filename using datetime data so it never gets overwritten.
# - The `Get-WmiObject` command pipes its output to `Select-Object *` which takes every possible bit of data about these programs.
# - This data is then piped to `Export-Csv` which gets passed your `$installed_programs_export` path.
# - This path is generated dynamically everytime with the datetime, so you never overwrite files and you know when you ran it.
$installed_programs_export=".\$(get-date -f "yyyy-MM-dd_HH_mm_s")-all_installed_programs.csv"
# $installed_programs_export=".\$(get-date -f "yyyy-MM-dd_HH_mm_s")-my_ou_installed_programs.csv"
$machine_count = (Get-Content $machine_path | Measure-Object).Count
Write-Host "Gathering inventory for $machine_count machines and exporting to $installed_programs_export ."
Write-Host "Please note, this may take quite a few minutes, depending on how many machines you asked this script to analyze."
Write-Host "It generally doesn't crash, though, so don't freak out. Just let it run."
Write-Host "Update: Trying a progress bar..."
# The properties below are the most useful, I've found, but it's up to you.
$properties = @("PSComputerName", "Vendor", "Name", "Caption", "Version", "Description", "InstallDate", "InstallSource", "LocalPackage", "PackageCache", "PackageName", "IdentifyingNumber", "InstallLocation", "Language", "PackageCode", "ProductID", "RegCompany", "RegOwner", "HelpLink", "HelpTelephone", "URLInfoAbout", "URLUpdateInfo", "InstallState", "AssignmentType", "__SERVER", "Transforms")
$programs = @()
$i = 0
foreach ($machine in (Get-Content $machine_path)){
$completion = (($i/$machine_count)*100)
Write-Progress -Activity "Cataloguing $machine..." -Status "Overall Progress: $completion %" -PercentComplete $completion
$machine_programs = Get-WmiObject win32_product -computername $machine -ErrorAction SilentlyContinue | Select-Object $properties
$programs += $machine_programs
Write-Host "$machine complete."
$i+=1
}
$programs | Export-Csv $installed_programs_export
Write-Host "Script complete. Please note: it is possible not all machines were inventoried. They may have been offline or misconfigured."
Write-Host "Check the machines in $machine_path against what showed up in $installed_programs_export to see which machines may be missing."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment