Getting domain Windows Server's licensing status

This PowerShell script performs the following steps:

# 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

"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