====== Getting domain Windows Server's licensing status ====== This PowerShell script performs the following steps: * Includes a hashtable **$licenseStatusDescriptions** that maps each `LicenseStatus` value to its corresponding description. When adding the results to the array, it uses this mapping to convert the numeric `LicenseStatus` to a descriptive string. * Queries all domain computers with an operating system that includes "Windows Server". * For each server, it retrieves the license status using the **Get-CimInstance** cmdlet. * Collects the results into an array. * Exports the results to a CSV file located at **C:\temp\WindowsServerLicenseStatus.csv**. # Import the Active Directory module Import-Module ActiveDirectory # Define a hashtable for license status descriptions $licenseStatusDescriptions = @{ 0 = 'Unlicensed' 1 = 'Licensed' 2 = 'OOBGrace (Out of Box Grace)' 3 = 'OOTGrace (Out of Tolerance Grace)' 4 = 'NonGenuineGrace' 5 = 'Notification' 6 = 'ExtendedGrace' } # Get all Windows Server machines in the domain $servers = Get-ADComputer -Filter "OperatingSystem -Like '*Windows Server*'" -Property Name, OperatingSystem # Initialize an array to store the results $results = @() foreach ($server in $servers) { # Get the license status from each server $licenseStatus = Get-CimInstance -ComputerName $server.Name -ClassName SoftwareLicensingProduct -Filter "Name like 'Windows%'" | Where-Object { $_.PartialProductKey } | Select-Object Description, LicenseStatus foreach ($status in $licenseStatus) { # Map the LicenseStatus to its description $statusDescription = $licenseStatusDescriptions[$status.LicenseStatus] # Add the result to the array $results += [PSCustomObject]@{ ServerName = $server.Name OperatingSystem = $server.OperatingSystem Description = $status.Description LicenseStatus = $statusDescription } } } # Export the results to a CSV file $results | Export-Csv -Path "C:\temp\WindowsServerLicenseStatus.csv" -NoTypeInformation {{:getwindowslicensestatus.jpg?nolink|}} ===== "LicensingServiceRemainingDays","SlmgrRemainingDays" ===== Here, the script modified so we get both the LicensingService countdown (from WMI) and the slmgr countdown (parsed from /xpr). It will export all results to CSV. # Import the Active Directory module Import-Module ActiveDirectory # Define a hashtable for license status descriptions $licenseStatusDescriptions = @{ 0 = 'Unlicensed' 1 = 'Licensed' 2 = 'OOBGrace (Out of Box Grace)' 3 = 'OOTGrace (Out of Tolerance Grace)' 4 = 'NonGenuineGrace' 5 = 'Notification' 6 = 'ExtendedGrace' } # Get all Windows Server machines in the domain $servers = Get-ADComputer -Filter "OperatingSystem -Like '*Windows Server*'" -Property Name, OperatingSystem # Initialize an array to store the results $results = @() foreach ($server in $servers) { try { $licenseStatus = Get-CimInstance -ComputerName $server.Name -ClassName SoftwareLicensingProduct -ErrorAction Stop | Where-Object { $_.PartialProductKey -and $_.Description -like '*TIMEBASED_EVAL*' } | Select-Object Description, LicenseStatus, EvaluationEndDate, GracePeriodRemaining } catch { Write-Warning "Failed to query WMI on $($server.Name): $_" continue } foreach ($status in $licenseStatus) { $statusDescription = $licenseStatusDescriptions[$status.LicenseStatus] # LicensingService calculation (WMI) $lsDays = $null if ($status.GracePeriodRemaining) { $lsDays = [math]::Floor($status.GracePeriodRemaining / 1440) if ($lsDays -lt 0) { $lsDays = 0 } } elseif ($status.EvaluationEndDate -and $status.EvaluationEndDate.Year -gt 1900) { $lsDays = ($status.EvaluationEndDate - (Get-Date)).Days if ($lsDays -lt 0) { $lsDays = 0 } } # slmgr /xpr parsing $slmgrDays = $null try { $slmgrOutput = Invoke-Command -ComputerName $server.Name -ScriptBlock { cscript.exe //Nologo "$env:SystemRoot\System32\slmgr.vbs" /xpr } if ($slmgrOutput -match 'expire.* (\d{1,2}/\d{1,2}/\d{4})') { $expireDate = [datetime]::ParseExact($matches[1], 'M/d/yyyy', $null) $slmgrDays = ($expireDate - (Get-Date)).Days if ($slmgrDays -lt 0) { $slmgrDays = 0 } } elseif ($slmgrOutput -match 'permanent') { $slmgrDays = 'Permanent' } } catch { Write-Warning "Failed to query slmgr on $($server.Name): $_" } $results += [PSCustomObject]@{ ServerName = $server.Name OperatingSystem = $server.OperatingSystem Description = $status.Description LicenseStatus = $statusDescription LicensingServiceRemainingDays = $lsDays SlmgrRemainingDays = $slmgrDays } } } # Export the results to a CSV file $results | Export-Csv -Path "C:\temp\WindowsServerLicenseStatus.csv" -NoTypeInformation -Encoding UTF8