Active-Directory Clients mit Powershell inventarisieren

powershell inventarisierung 1111

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.

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

weitere Beiträge zu Active Directory und Powershell die euch interessieren könnten