====== 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