How to Efficiently Check Windows Activation & License Verification with PowerShell

Key takeaways

  • Automated compliance check: The script automates the process of checking Windows activation and licensing status, ensuring compliance across multiple systems.
  • Error identification and resolution: It identifies specific Windows activation errors and provides troubleshooting steps, aiding in quick resolution.
  • Efficiency in IT management: Automates a traditionally manual process, saving time and resources for IT professionals and MSPs.
  • Supports legal and security standards: Helps maintain legal licensing requirements and ensures systems receive necessary updates for security.
  • Versatile for modern Windows systems: Designed for Windows 10 and Windows Server 2016 onwards, making it suitable for contemporary IT environments.
  • Integration with IT management tools: Can be incorporated into broader IT management solutions like NinjaOne for enhanced monitoring and management.
  • User-friendly output: The script provides easy-to-understand output, making it accessible for IT professionals with varying levels of expertise.

Introduction

Windows activation and licensing are critical components in maintaining the legality and functionality of Windows systems in the IT environment. Ensuring that Windows is properly licensed and activated is not just a legal requirement but also a prerequisite for receiving important updates and support. In this context, PowerShell scripts emerge as powerful tools for IT professionals and Managed Service Providers (MSPs) to automate and streamline the process of checking Windows activation and license status.

Background

The provided PowerShell script is designed to detect the activation and license status of Windows operating systems. It is particularly valuable in environments where multiple machines need to be managed, ensuring that all are compliant with Microsoft’s licensing requirements. This script is a boon for IT professionals and MSPs, allowing them to quickly identify unlicensed or non-activated Windows installations, thereby avoiding potential legal issues and ensuring system integrity.

The script

#Requires -Version 5.1

<#
.SYNOPSIS
    Condition script for detecting activation and license status of Windows.
.DESCRIPTION
    Condition script for detecting activation and license status of Windows.
    Exit codes:
    0 = Activated and Licensed
    2 = Unlicensed, but under a grace period
    3 = Not Activated and Unlicensed
.NOTES
    Minimum OS Architecture Supported: Windows 10, Windows Server 2016
    Release Notes: Renamed script
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param ()

begin {
    # https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn502528(v=ws.11)
    $NotificationReasons = {
        [PSCustomObject]@{
            ErrorCode            = "0xC004C001"
            ErrorMessage         = "The activation server determined the specified product key is invalid"
            ActivationType       = "MAK"
            PossibleCause        = "An invalid MAK was entered."
            TroubleshootingSteps = "Verify that the key is the MAK provided by Microsoft. Contact the Microsoft Activation Call Center to verify that the MAK is valid."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004C003"
            ErrorMessage         = "The activation server determined the specified product key has been blocked"
            ActivationType       = "MAK"
            PossibleCause        = "The MAK is blocked on the activation server."
            TroubleshootingSteps = "Contact the Microsoft Activation Call Center to obtain a new MAK and install/activate the system."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004C008"
            ErrorMessage         = "The activation server reported that the product key has exceeded its unlock limit."
            ActivationType       = "KMS"
            PossibleCause        = "The KMS key has exceeded the activation limit."
            TroubleshootingSteps = "KMS host keys will activate up to 10 times on six different computers. If more activations are necessary, contact the Microsoft Activation Call Center."       
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004C020"
            ErrorMessage         = "The activation server reported that the Multiple Activation Key has exceeded its limit."
            ActivationType       = "MAK"
            PossibleCause        = "The MAK has exceeded the activation limit."
            TroubleshootingSteps = "MAKs by design have a limited number of activations. Contact the Microsoft Activation Call Center."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004C021"
            ErrorMessage         = "The activation server reported that the Multiple Activation Key extension limit has been exceeded."
            ActivationType       = "MAK"
            PossibleCause        = "The MAK has exceeded the activation limit."
            TroubleshootingSteps = "MAKs by design have a limited number of activations. Contact the Microsoft Activation Call Center."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F009"
            ErrorMessage         = "The Software Protection Service reported that the grace period expired."
            ActivationType       = "MAK"
            PossibleCause        = "The grace period expired before the system was activated. Now, the system is in the Notifications state."
            TroubleshootingSteps = "See the section User Experience."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F00F"
            ErrorMessage         = "The Software Licensing Server reported that the hardware ID binding is beyond level the of tolerance."
            ActivationType       = "MAK/KMS client/KMS host"
            PossibleCause        = "The hardware has changed or the drivers were updated on the system."
            TroubleshootingSteps = "MAK: Reactivate the system during the OOT grace period using either online or phone activation. KMS: Restart, or run slmgr.vbs /ato."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F014"
            ErrorMessage         = "The Software Protection Service reported that the product key is not available"
            ActivationType       = "MAK/KMS client"
            PossibleCause        = "No product keys are installed on the system."
            TroubleshootingSteps = "Install a MAK product key, or install a KMS Setup key found in \\sources\\Product.ini on the installation media."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F02C"
            ErrorMessage         = "The Software Protection Service reported that the format for the offline activation data is incorrect."
            ActivationType       = "MAK/KMS client"
            PossibleCause        = "The system has detected that the data entered during phone activation is not valid."
            TroubleshootingSteps = "Verify that the CID is correctly entered."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F038"
            ErrorMessage         = "The Software Protection Service reported that the computer could not be activated. The count reported by your Key Management Service (KMS) is insufficient. Please contact your system administrator."
            ActivationType       = "KMS client"
            PossibleCause        = "The count on the KMS host is not high enough. The KMS count must be ≥5 for Windows Server or ≥25 for Windows client."
            TroubleshootingSteps = "More computers are needed in the KMS pool for KMS clients to activate. Run Slmgr.vbs /dli to get the current count on the KMS host."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F039"
            ErrorMessage         = "The Software Protection Service reported that the computer could not be activated. The Key Management Service (KMS) is not enabled."
            ActivationType       = "KMS client"
            PossibleCause        = "This error occurs when a KMS request is not answered."
            TroubleshootingSteps = "Troubleshoot the network connection between the KMS host and the client. Make sure that TCP port 1688 (default) is not blocked by a firewall or otherwise filtered."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F041"
            ErrorMessage         = "The Software Licensing Service determined that the Key Management Service (KMS) is not activated. KMS needs to be activated. Please contact system administrator."
            ActivationType       = "KMS client"
            PossibleCause        = "The KMS host is not activated."
            TroubleshootingSteps = "Activate the KMS host with either online or phone activation."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F042"
            ErrorMessage         = "The Software Protection Service determined that the specified Key Management Service (KMS) cannot be used."
            ActivationType       = "KMS client"
            PossibleCause        = "Mismatch between the KMS client and the KMS host."
            TroubleshootingSteps = "This error occurs when a KMS client contacts a KMS host that cannot activate the client software. This can be common in mixed environments that contain application and operating system-specific KMS hosts, for example."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F050"
            ErrorMessage         = "The Software Protection Service reported that the product key is invalid."
            ActivationType       = "KMS, KMS client, MAK"
            PossibleCause        = "This can be caused by a typo in the KMS key or by typing in a Beta key on a Released version of the operating system."
            TroubleshootingSteps = "Install the appropriate KMS key on the corresponding version of Windows. Check the spelling. If the key is being copied and pasted, make sure that em dashes have not been substituted for the dashes in the key."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F051"
            ErrorMessage         = "The Software Protection Service reported that the product key is blocked."
            ActivationType       = "MAK/KMS"
            PossibleCause        = "The product key on the activation server is blocked by Microsoft."
            TroubleshootingSteps = "Obtain a new MAK/KMS key, install it on the system, and activate."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F074"
            ErrorMessage         = "The Software Protection Service reported that the computer could not be activated. No Key Management Service (KMS) could be contacted. Please see the Application Event Log for additional information."
            ActivationType       = "KMS Client"
            PossibleCause        = "All KMS host systems  returned an error."
            TroubleshootingSteps = "Troubleshoot errors from each event ID 12288 associated with the activation attempt."
        }
        [PSCustomObject]@{
            ErrorCode            = "0xC004F06C"
            ErrorMessage         = "The Software Protection Service reported that the computer could not be activated. The Key Management Service (KMS) determined that the request timestamp is invalid."
            ActivationType       = "KMS client"
            PossibleCause        = "The system time on the client computer is too different from the time on the KMS host."
            TroubleshootingSteps = "Time sync is important to system and network security for a variety of reasons. Fix this issue by changing the system time on the client to sync with the KMS. Use of a Network Time Protocol (NTP) time source or Active Directory Domain Services for time synchronization is recommended. This issue uses UTP time and is independent of Time Zone selection."
        }
        [PSCustomObject]@{
            ErrorCode            = "0x80070005"
            ErrorMessage         = "Access denied. The requested action requires elevated privileges."
            ActivationType       = "KMS client/MAK/KMS host"
            PossibleCause        = "User Account Control (UAC) prohibits activation processes from running in a non-elevated command prompt."
            TroubleshootingSteps = "Run slmgr.vbs from an elevated command prompt. Right-click cmd.exe, and then click Run as Administrator."
        }
        [PSCustomObject]@{
            ErrorCode            = "0x8007232A"
            ErrorMessage         = "DNS server failure."
            ActivationType       = "KMS host"
            PossibleCause        = "The system has network or DNS issues."
            TroubleshootingSteps = "Troubleshoot network and DNS."
        }
        [PSCustomObject]@{
            ErrorCode            = "0x8007232B"
            ErrorMessage         = "DNS name does not exist."
            ActivationType       = "KMS client"
            PossibleCause        = "The KMS client cannot find KMS SRV RRs in DNS. If a KMS host does not exist on the network, a MAK should be installed."
            TroubleshootingSteps = "Confirm that a KMS host has been installed and DNS publishing is enabled (default). If DNS is unavailable, point the KMS client to the KMS host by using slmgr.vbs /skms \u003ckms_host_name\u003e. Optionally, obtain and install a MAK; then, activate the system. Finally, troubleshoot DNS."
        }
        [PSCustomObject]@{
            ErrorCode            = "0x800706BA"
            ErrorMessage         = "The RPC server is unavailable."
            ActivationType       = "KMS client"
            PossibleCause        = "Firewall settings are not configured on the KMS host, or DNS SRV records are stale."
            TroubleshootingSteps = "Ensure the Key Management Service firewall exception is enabled on the KMS host computer. Ensure that SRV records point to a valid KMS host. Troubleshoot network connections."
        }
        [PSCustomObject]@{
            ErrorCode            = "0x8007251D"
            ErrorMessage         = "No records found for given DNS query."
            ActivationType       = "KMS client"
            PossibleCause        = "The KMS client cannot find KMS SRV RRs in DNS."
            TroubleshootingSteps = "Troubleshoot network connections and DNS."
        }
    }.Invoke()
}
process {
    Write-Host ""

    $LicenseStatus = Get-CimInstance -ClassName "SoftwareLicensingProduct" -Filter "Name like 'Windows%'" -ErrorAction SilentlyContinue |
        Where-Object { $_.PartialProductKey } |
        Select-Object -ExpandProperty LicenseStatus

    $ActivationNumber = switch ($LicenseStatus) {
        0 { 3 }
        1 { 0 }
        2 { 2 }
        3 { 2 }
        4 { 3 }
        5 { 3 }
        6 { 2 }
        default { 3 }
    }

    $Result = cscript.exe C:\Windows\system32\slmgr.vbs -dli
    $Result | Select-Object -Skip 4 | Out-String | Write-Host
    $Notification = $Result -split [System.Environment]::NewLine | Where-Object { $_ -match "^Notification Reason: .*" }
    Write-Host ""
    if ($Notification) {
        $NotificationCode = $($($Notification -split ': ')[1] -split '\.')[0]
        Write-Host "[Error] KMS Activation Error Found."
        if ($NotificationCode -like "0xC004F200") { Write-Host "Non-Genuine" }
        elseif ($NotificationCode -like "0xC004F009") { Write-Host "Grace Time Expired" }
        else {
            $NotificationReasons | Where-Object { $_.ErrorCode -like "$NotificationCode" } | Out-String | Write-Host
        }
    }
    if ($Result -like "*Eval*") {
        Write-Host "Evaluation Licensed"
        exit 5 # Is Activated but is an Evaluation license
    }
    exit $ActivationNumber
}
end {
    
    
    
}

 

Access over 300+ scripts in the NinjaOne Dojo

Get Access

Detailed breakdown

The script begins by defining a series of potential error codes and messages related to Windows activation. These are encapsulated within a PowerShell custom object, providing detailed information on the nature of the error, the type of activation (e.g., MAK, KMS), and troubleshooting steps.

In the process block, the script executes a series of commands:

  • It retrieves the license status of Windows products using the Get-CimInstance cmdlet.
  • The license status is then evaluated through a switch statement, translating it into an exit code that represents different states of activation and licensing.
  • It runs slmgr.vbs -dli, a script that provides detailed information about Windows activation and licensing status.
  • The script parses the output of slmgr.vbs to identify any specific activation errors and provides the corresponding troubleshooting information from the earlier defined custom objects.

Potential use cases

Imagine an MSP managing the IT infrastructure for a medium-sized business. They can schedule this script to run periodically across all Windows machines. If a machine is found with a non-activated or unlicensed Windows installation, the script can alert the MSP, enabling them to take corrective action promptly.

Comparisons

Traditional methods of checking Windows activation involve manual checks on each system or using disparate tools, which can be time-consuming and inconsistent. This script offers a centralized, automated approach, ensuring consistency and saving time.

FAQs

  • How do I run this script?
    • Run the script in PowerShell as an administrator.
  • Will this script activate Windows for me?
    • No, it only checks the activation status and provides troubleshooting steps.
  • Can this script run on all Windows versions?
    • It is designed for Windows 10 and Windows Server 2016 and above.

Implications

Incorrectly licensed or non-activated Windows systems can pose significant security risks, as they may not receive critical updates. This script helps maintain compliance and security standards within an IT infrastructure.

Recommendations

  • Regularly schedule the script to run across all Windows machines in your network.
  • Review and act on the script’s output promptly to maintain compliance.
  • Ensure that PowerShell execution policies allow the running of scripts.

Final thoughts

In the realm of IT management, tools like NinjaOne can complement this PowerShell script by providing a comprehensive platform for monitoring, managing, and automating IT tasks. Integrating such scripts into a broader IT management solution like NinjaOne can enhance efficiency, ensure compliance, and maintain system integrity across an organization’s IT infrastructure.

Add a Comment

Your email address will not be published. Required fields are marked *

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).