Mit dem folgenden Script werden die Client der Active-Directory mit Powershell inventarisiert. Genau gesagt erhält man nach dem Durchlauf des Script auf einem DomainController, mehrere CSV-Dateien mit den Informationen über die installierte Software, BIOS Informationen und Mac-Addressen. Das ist natürlich besoners nützlich wenn man keine Software-Inventory oder Management-Lösung hat.
Inhaltsübersicht Verbergen
Welche Voraussetzungen benötigt das Script
- installiertes 7Zip auf dem Domain-Controller auf dem das Script ausgeführt wird
- Script muss unter einem Nutzer mit lokalen Adminrechten (auf den Clients) ausgeführt werden. In der Regel: Dom\Administrator
Sollte es nicht klappen bzw. Verbindungsfehler auswerfen, könnt ihr hier nachlesen, was auf den Clients aktiviert sein muss um Powershell auf Remotemaschinen ausführen zu können.
Abschnitte des Scriptes
Konfiguration
$application_blacklist=@("Microsoft Office Shared*","Microsoft Office IME *","Microsoft Office Proofing *","Microsoft Office Proof *","Microsoft Office Access MUI*"); # exempt this applications from report
$computer_blacklist=@("esx","nas") # exempt this clients from the report
$ad_LimitResultsPerDC=2500;
$transfer_path="\\dc01.mj.local\transfer"
$cleanup_created_files=1 # 0=html report will not be deleted, 1=html report will deleted at the end
$cleanup_files=@()
$zip_this_files=@()
$auditfile_path="c:\temp"
$7zip_proc="C:\Program Files\7-Zip\7z.exe"
$7Zip_addfiles="c:\temp\ad-get_SoftwareInventory_*.csv"
$log = "c:\temp\logfile_$scriptname.txt"
Active-Directory Clients auslesen
Get-ADComputer –Filter * -ResultSetSize $ad_LimitResultsPerDC -Properties Name -Server $selected_domaincontroller
installierte Software mit Powershell auslesen (32 bit & 64 bit Windows OS)
$os_arch=(Get-WmiObject Win32_OperatingSystem -ComputerName $computername).OSArchitecture
Write-Host "- OS Arch:"$os_arch
try{
if($os_arch -eq "64-bit"){
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$computername,'Registry64')
}else{
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$computername,'Registry32')
}
}
catch{
"==> ERROR "
}
finally{
}
foreach($UninstallKey in $UninstallKeys){
$regkey=$reg.OpenSubKey($UninstallKey)
if($regkey){
$subkeys=$regkey.GetSubKeyNames()
foreach($key in $subkeys){
$thisKey=$UninstallKey+”\\”+$key
$thisSubKey=$reg.OpenSubKey($thisKey)
#application blacklist
$appl_blacklisted=0
foreach($appl_bl in $application_blacklist){
if($thisSubKey.GetValue(“DisplayName”) -like $appl_bl){
$appl_blacklisted=1
}
}
if($appl_blacklisted -eq 0){
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name “ComputerName” -Value $computername
$obj | Add-Member -MemberType NoteProperty -Name “DNSHostName” -Value $pc.DNSHostName
$obj | Add-Member -MemberType NoteProperty -Name “ObjectGUID” -Value $pc.ObjectGUID
$obj | Add-Member -MemberType NoteProperty -Name “SID” -Value $pc.SID
$obj | Add-Member -MemberType NoteProperty -Name “DisplayName” -Value $($thisSubKey.GetValue(“DisplayName”))
$obj | Add-Member -MemberType NoteProperty -Name “DisplayVersion” -Value $($thisSubKey.GetValue(“DisplayVersion”))
$obj | Add-Member -MemberType NoteProperty -Name “InstallDate” -Value $($thisSubKey.GetValue(“InstallDate”))
$obj | Add-Member -MemberType NoteProperty -Name “InstallLocation” -Value $($thisSubKey.GetValue(“InstallLocation”))
$obj | Add-Member -MemberType NoteProperty -Name “Publisher” -Value $($thisSubKey.GetValue(“Publisher”))
$software_array += $obj
$app_name=$thisSubKey.GetValue(“DisplayName”)
$app_name+="_"+$thisSubKey.GetValue(“DisplayVersion”)
if($applications_overview.ContainsKey($app_name)-contains $false){
$applications_overview.$app_name=@{}
$applications_overview.$app_name=@($computername)
}else{
$applications_overview.$app_name+=$computername
}
}
}
}else{
write-host "- subkey don't exists:"$UninstallKey
}
}
Bios Informationen mit Powershell auslesen
get-wmiobject win32_bios -ComputerName $computername | Select-Object -Property SMBIOSBIOSVersion,Manufacturer,Name,SerialNumber,Version | Export-Csv $csv_biosinfo_file
Mac-Addressen auslesen
Get-WmiObject win32_networkadapterconfiguration -ComputerName $computername | Select-Object -Property description, macaddress | Export-Csv $csv_mac_file
installierte Windows Updates auslesen
get-wmiobject -class win32_quickfixengineering -ComputerName $computername | Select-Object -Property Source,Description,HotFixID,InstalledBy,InstalledOn | Export-Csv $csv_wu_file
Das gesamte Script
# Scriptname: ad-get_SoftwareInventory_Report
# Author: Mathias Jäkel
# Version: 1.20210212 1
#
# description: -
# Requirements:
# - powershell 4.0
# - MS AD Management CMDlets (Windows 2012)
#
# Configuration:
#
#### Configuration ####
$scriptname="ad-get_SoftwareInventory_Report"
$application_blacklist=@("Microsoft Office Shared*","Microsoft Office IME *","Microsoft Office Proofing *","Microsoft Office Proof *","Microsoft Office Access MUI*"); # exempt this applications from report
$computer_blacklist=@("cctv","esx","nas") # exempt this clients from the report
$ad_LimitResultsPerDC=2500;
$transfer_path="\\dc01.mj.local\transfer"
$cleanup_created_files=1 # 0=html report will not be deleted, 1=html report will deleted at the end
$cleanup_files=@()
$zip_this_files=@()
$auditfile_path="c:\temp"
$7zip_proc="C:\Program Files\7-Zip\7z.exe"
$7Zip_addfiles="c:\temp\ad-get_SoftwareInventory_*.csv"
$log = "c:\temp\logfile_$scriptname.txt"
$computers_per_file=30
$UninstallKeys=@(”SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall”,”SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”) # location of installed software inside Win.-registry
#### Configuration End ####
start-transcript $log
$software_array = @()
$curDate = Get-Date -format "yyyy-dd-MM_HHmm"
$ad_name=$env:USERDOMAIN.ToLower()
$resultfile_csv=$auditfile_path+"\"+$scriptname+"_"+$ad_name+"_"+$curDate+".csv"
$resultfile_zip=$auditfile_path+"\"+$scriptname+"_"+$ad_name+"_"+$curDate+".7z"
$computer_is_offline=@()
$computer_is_blacklisted=@()
$computer_counter=1;
#### create clientlist
if((Test-Path $auditfile_path) -eq $False){ New-Item -ItemType directory -Path $auditfile_path}
$selected_domaincontroller=$env:LOGONSERVER
$selected_domaincontroller=$selected_domaincontroller -replace("\\","")
write-host "- selected domaincontroller:"$selected_domaincontroller
### Pingcheck 1 - with autodetected Domaincrontroller
###
$Pingcheckresult_failed=0
if (-not (Test-Connection -ComputerName $selected_domaincontroller -Quiet)){
$Pingcheckresult_failed = 1;
Write-Host "- Pingcheck 1 failed! skip server "$selected_domaincontroller
}else{
Write-Host "- Pingcheck 1 successful: "$selected_domaincontroller
}
if ($Pingcheckresult_failed -eq 0){
$results_get_adcomputer=Get-ADComputer –Filter * -ResultSetSize $ad_LimitResultsPerDC -Properties Name -Server $selected_domaincontroller
}
#### Get Data from every Client
write-host "- ad-computers found: "$results_get_adcomputer.count
#### GET Software Inventory List
$applications_overview=@{}
$computer_counter=0
foreach($pc in $results_get_adcomputer){
$computer_blacklisted_result=0
foreach($pc_bl in $computer_blacklist){
$pc_bl_="*"+$pc_bl+"*"
if($pc.Name.ToString() -like $pc_bl_){
$computer_blacklisted_result=1
write-host "- blacklisted!"
}
}
if($computer_blacklisted_result -eq 0){
$computername=$pc.DNSHostName
if($computername.Length -lt 3){
$computername=$pc.Name
}
$Pingcheckresult_failed=0
if (-not (Test-Connection -ComputerName $computername -Quiet -Count 1)){
$Pingcheckresult_failed = 1;
Write-Host "- Pingcheck failed: "$computername" ("$computer_counter")"
$computer_is_offline+=$computername
}else{
Write-Host "- Pingcheck successful: "$computername" ("$computer_counter")"
}
if($Pingcheckresult_failed -eq 0){
#### get Bios INFO
write-host "- get BIOS Info"
$csv_biosinfo_file=$auditfile_path+"\"+$scriptname+"_"+$ad_name+"_biosinfo_"+$computername+".csv"
$cleanup_files+=$csv_biosinfo_file
$zip_this_files+=$csv_biosinfo_file
try{
get-wmiobject win32_bios -ComputerName $computername | Select-Object -Property SMBIOSBIOSVersion,Manufacturer,Name,SerialNumber,Version | Export-Csv $csv_biosinfo_file
}
catch{
"==> ERROR "
}
finally{
}
#### get Mac_Addresses INFO
write-host "- get Mac_Addresses"
$csv_mac_file=$auditfile_path+"\"+$scriptname+"_"+$ad_name+"_macaddr_"+$computername+".csv"
$cleanup_files+=$csv_mac_file
$zip_this_files+=$csv_mac_file
try{
Get-WmiObject win32_networkadapterconfiguration -ComputerName $computername | Select-Object -Property description, macaddress | Export-Csv $csv_mac_file
}
catch{
"==> ERROR "
}
finally{
}
#### get installed Windows Updates
write-host "- get Windows Updates"
$csv_wu_file=$auditfile_path+"\"+$scriptname+"_"+$ad_name+"_WU_"+$computername+".csv"
$cleanup_files+=$csv_wu_file
$zip_this_files+=$csv_wu_file
try{
get-wmiobject -class win32_quickfixengineering -ComputerName $computername | Select-Object -Property Source,Description,HotFixID,InstalledBy,InstalledOn | Export-Csv $csv_wu_file
}
catch{
"==> ERROR "
}
finally{
}
#### get installed Software
write-host "- get Softwarelist "
$os_arch=(Get-WmiObject Win32_OperatingSystem -ComputerName $computername).OSArchitecture
Write-Host "- OS Arch:"$os_arch
try{
if($os_arch -eq "64-bit"){
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$computername,'Registry64')
}else{
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$computername,'Registry32')
}
}
catch{
"==> ERROR "
}
finally{
}
foreach($UninstallKey in $UninstallKeys){
$regkey=$reg.OpenSubKey($UninstallKey)
if($regkey){
$subkeys=$regkey.GetSubKeyNames()
foreach($key in $subkeys){
$thisKey=$UninstallKey+”\\”+$key
$thisSubKey=$reg.OpenSubKey($thisKey)
#application blacklist
$appl_blacklisted=0
foreach($appl_bl in $application_blacklist){
if($thisSubKey.GetValue(“DisplayName”) -like $appl_bl){
$appl_blacklisted=1
}
}
if($appl_blacklisted -eq 0){
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name “ComputerName” -Value $computername
$obj | Add-Member -MemberType NoteProperty -Name “DNSHostName” -Value $pc.DNSHostName
$obj | Add-Member -MemberType NoteProperty -Name “ObjectGUID” -Value $pc.ObjectGUID
$obj | Add-Member -MemberType NoteProperty -Name “SID” -Value $pc.SID
$obj | Add-Member -MemberType NoteProperty -Name “DisplayName” -Value $($thisSubKey.GetValue(“DisplayName”))
$obj | Add-Member -MemberType NoteProperty -Name “DisplayVersion” -Value $($thisSubKey.GetValue(“DisplayVersion”))
$obj | Add-Member -MemberType NoteProperty -Name “InstallDate” -Value $($thisSubKey.GetValue(“InstallDate”))
$obj | Add-Member -MemberType NoteProperty -Name “InstallLocation” -Value $($thisSubKey.GetValue(“InstallLocation”))
$obj | Add-Member -MemberType NoteProperty -Name “Publisher” -Value $($thisSubKey.GetValue(“Publisher”))
$software_array += $obj
$app_name=$thisSubKey.GetValue(“DisplayName”)
$app_name+="_"+$thisSubKey.GetValue(“DisplayVersion”)
if($applications_overview.ContainsKey($app_name)-contains $false){
$applications_overview.$app_name=@{}
$applications_overview.$app_name=@($computername)
}else{
$applications_overview.$app_name+=$computername
}
}
}
}else{
write-host "- subkey don't exists:"$UninstallKey
}
}
}
}else{
write-host "- "$pc.Name" is on blacklist"
$computer_is_blacklisted+=$pc.Name
}
$computer_counter++
## send collected Data
$modulo=$computer_counter%$computers_per_file
if($modulo -eq 0){
###
$new_suffix="$computer_counter."
$resultfile_csv_=$resultfile_csv.replace(".",$new_suffix)
$resultfile_zip_=$resultfile_zip.replace(".",$new_suffix)
$cleanup_files+=$resultfile_csv_
$cleanup_files+=$resultfile_zip_
### export Softwareinventory to CSV
$software_array | export-csv $resultfile_csv_
$software_array=@()
$cleanup_files+=$resultfile_csv_
$zip_this_files+=$resultfile_csv_
### configure 7Zip
if(Test-Path $7zip_proc){
$7zip_arg="a -mx=9 -mmt=off "+$resultfile_zip_+" "+$7Zip_addfiles
$7zip_error_file=$auditfile_path+"\7zip_error.txt"
$7zip_output_file=$auditfile_path+"\7zip_output.txt"
$cleanup_files+=$7zip_error_file
$cleanup_files+=$7zip_output_file
write-host "- 7zip: create archive "$resultfile_zip_"..."
write-host "- 7zip: "$7zip_proc" "$7zip_arg
start-process -FilePath $7zip_proc -ArgumentList $7zip_arg -RedirectStandardError $7zip_error_file -RedirectStandardOutput $7zip_output_file -NoNewWindow -Wait
}else{
write-host "- ERROR: 7zip was not found"
}
### transfer data to reporting-server
if(Test-Path $resultfile_zip_){
write-host "- copy "$resultfile_zip_" to "$transfer_path
copy-Item -Path $resultfile_zip_ -Destination $transfer_path
}else{
write-host "- ERROR: "$resultfile_zip_" not copied!"
}
### CLEANUP
if($cleanup_created_files -gt 0){
if(Test-Path $resultfile_csv_){Remove-Item($resultfile_csv_)}
if(Test-Path $resultfile_zip_){Remove-Item($resultfile_zip_)}
foreach ($delete_file in $cleanup_files){
if(Test-Path $delete_file){Remove-Item($delete_file)}
}
}
###
}
}
$new_suffix="99999999."
$resultfile_csv_=$resultfile_csv.replace(".",$new_suffix)
$resultfile_zip_=$resultfile_zip.replace(".",$new_suffix)
$cleanup_files+=$resultfile_csv_
$cleanup_files+=$resultfile_zip_
### export Softwareinventory to CSV
$software_array | export-csv $resultfile_csv_
$software_array=@()
$zip_this_files+=$resultfile_csv_
### configure 7Zip
if(Test-Path $7zip_proc){
$7zip_arg="a -mx=9 -mmt=off "+$resultfile_zip_+" "+$7Zip_addfiles
$7zip_error_file=$auditfile_path+"\7zip_error.txt"
$7zip_output_file=$auditfile_path+"\7zip_output.txt"
$cleanup_files+=$7zip_error_file
$cleanup_files+=$7zip_output_file
write-host "- 7zip: create archive "$resultfile_zip_"..."
write-host "- 7zip: "$7zip_proc" "$7zip_arg
start-process -FilePath $7zip_proc -ArgumentList $7zip_arg -RedirectStandardError $7zip_error_file -RedirectStandardOutput $7zip_output_file -NoNewWindow -Wait
}else{
write-host "- ERROR: 7zip was not found"
}
### transfer data to reporting-server
if(Test-Path $resultfile_zip_){
write-host "- copy "$resultfile_zip_" to "$transfer_path
copy-Item -Path $resultfile_zip_ -Destination $transfer_path
}else{
write-host "- ERROR: "$resultfile_zip_" not copied!"
}
### CLEANUP
if($cleanup_created_files -gt 0){
foreach ($delete_file in $cleanup_files){
if(Test-Path $delete_file){Remove-Item($delete_file)}
}
}
stop-transcript