Windows Activation Methods

Overview:

1. Retail:
– There are ‘lifetime’ and ‘limited’ (1-2 years) variants
– This can be used on non-domain joined machines, but not Mac OS – those are not real computers.

2. Original Equipment Manufacturer (OEM):
– Makers such as Dell, HP, Compaq, IBM, will sell machines with built-in keys.
– Licensing duration is ‘forever’ (or until such equipment belong to the trash guys, whichever comes first).
– Serial is applicable only for the single computer it has been installed upon.
– This may not be transferable to another physical machine. There are *ehem* keygens for such special occasions.
– $_ may be transferable to a ‘physical to virtual’ (P2V) converted machine

3. Volume Licensing:

  1. Key Management Service (KMS): is meant for seamless integration with Active Directory using a single KMS host – multiple KMS hosts or setups without Dynamic Domain Name System will require special workarounds. Source: https://docs.microsoft.com/en-us/previous-versions/tn-archive/ff793419(v%3dtechnet.10)
     Command to find KMS Server: nslookup -type=srv _vlmcs._tcp
  2. Multiple Activation Key (MAK): is a one-time activation through Microsoft’s hosted activation services, with no renewals required.
  3. Automatic Virtual Machine Activation (AVMA): is good for Windows Virtual machines being hosted by a Windows Server Datacenter physical machine. No licensing count is necessary, although special activation commands are required.

4. Illegitimate licensing:
– I don’t know anything about that

Goal:

How To Get There:

You’re in luck. I’ve written 3 functions for the cases of Retail licensing (which is similar to MAK),  KMS for domain joined computers, and AVMA for virtual machines running Windows. No need to give me money for doing this. I enjoy writing chicken scratch scripts.

# Normal method with a retail key

$remoteWindows="SHERVER01","SHERVER02"
$licenseKey="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"

function activateComputers{
    param (
        [string[]]$computerNames,
        [string][ValidatePattern('^\S{5}-\S{5}-\S{5}-\S{5}-\S{5}$')]$licenseKey        
        )

    function activateWindows{
        param([string]$key)
        $licensingService = get-wmiObject -query "select * from SoftwareLicensingService"
        $null = $licensingService.InstallProductKey($key);
        $null = $licensingService.RefreshLicenseStatus();
        #Get-CimInstance -ClassName SoftwareLicensingProduct|where {$_.PartialProductKey}|select Description, LicenseStatus
    }
 
    foreach ($machine in $computerNames){
        $isLocal=$guestVm -match "$($env:computername)*"
        if($isLocal){
            activateWindows $licenseKey
            }
        else{
            # Activate Windows via Win RM
            Invoke-Command -computer $remoteWindows -ScriptBlock{
                                        param($importedFunc,$importedKey)
                                        [ScriptBlock]::Create($importedFunc).Invoke($importedKey);                                
                                    } -Args ${function:activateWindows},$licenseKey
 
            }
    }
    #Validate licensing status
    #Get-CimInstance -computername $remoteWindows -ClassName SoftwareLicensingProduct|where {$_.PartialProductKey}|select Description, LicenseStatus
    function checkActivation($computername=$env:computername){
        $state = Get-WmiObject -ComputerName $computername -Query "Select * from SoftwareLicensingProduct Where PartialProductKey IS NOT NULL AND ApplicationID='55c92734-d682-4d71-983e-d6ec3f16059f'"
        $activationState=Switch ($state.LicenseStatus){
            0 {"Unlicensed"}
            1 {"Licensed"}
            2 {"Out-of-Box Grace Period"}
            3 {"Out-of-Tolerance Grace Period"}
            4 {"Non-Genuine Grace Period"}
            5 {"Notification"}
            6 {"ExtendedGrace"}
        }
        return $activationState
    }
    $computerNames|%{"$_ status`t: $(checkActivation $_)"}
}
 
activateComputers $remoteWindows $licenseKey






# KMS Activation

# Assuming that the KMS Server is already available on the network
function activateWindowsKms($kmsKey){    
  $kmsKeys=@{ #source: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj612867(v=ws.11)
              'Microsoft Windows Server 2016 Datacenter'='CB7KF-BWN84-R7R2Y-793K2-8XDDG';
              'Microsoft Windows Server 2016 Standard'='WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY';
              'Microsoft Windows Server 2016 Essentials'='JCKRF-N37P4-C2D82-9YXRT-4M63B';
              'Microsoft Windows 10 Pro'='W269N-WFGWX-YVC9B-4J6C9-T83GX';
              'Microsoft Windows 10 Pro N'='MH37W-N47XK-V7XM9-C7227-GCQG9';
              'Microsoft Windows 10 Enterprise'='NPPR9-FWDCX-D2C8J-H872K-2YT43';
              'Microsoft Windows 10 Enterprise N'='DPH2V-TTNVB-4X9Q3-TJR4H-KHJW4';
              'Microsoft Windows 10 Education'='NW6C2-QMPVW-D7KKK-3GKT6-VCFB2';
              'Microsoft Windows 10 Education N'='2WH4N-8QGBV-H22JP-CT43Q-MDWWJ';
              'Microsoft Windows 10 Enterprise 2015 LTSB'='WNMTR-4C88C-JK8YV-HQ7T2-76DF9';
              'Microsoft Windows 10 Enterprise 2015 LTSB N'='2F77B-TNFGY-69QQF-B8YKP-D69TJ';
              'Microsoft Windows 10 Enterprise 2016 LTSB'='DCPHK-NFMTC-H88MJ-PFHPY-QJ4BJ';
              'Microsoft Windows 10 Enterprise 2016 LTSB N'='QFFDN-GRT3P-VKWWX-X7T3R-8B639';
              # source: https://docs.microsoft.com/en-us/windows-server/get-started/kmsclientkeys
              'Microsoft Windows Server 2019 Datacenter'='WMDGN-G9PQG-XVVXX-R3X43-63DFG';
              'Microsoft Windows Server 2019 Standard'='N69G4-B89J2-4G8F4-WWYCC-J464C';
              'Microsoft Windows Server 2019 Essentials'='WVDHN-86M7X-466P6-VHXV7-YY726';
              'Microsoft Windows 10 Enterprise LTSC 2019'='M7XTQ-FN8P6-TTKYV-9D4CC-J462D';
              'Microsoft Windows 10 Enterprise N LTSC 2019'='92NFX-8DJQP-P6BBQ-THF9C-7CG2H';
            }  
  $ErrorActionPreference = 'stop'  
  
  function genericActivation{
    $kms = nslookup -type=srv _vlmcs._tcp
    $kmshost = .{$kms|%{$match=$_ -match 'svr hostname   = (.*)';if($match){return $matches[1]}}} 
    $null=slmgr.vbs /skms "$kmshost`:1688"
    $null=Slmgr.vbs /ato
    $activationStatus=(Get-CimInstance SoftwareLicensingProduct -Filter "Name like 'Windows%'"|?{$_.PartialProductKey}).LicenseStatus
    if($activationStatus){
      return $true
    }else{
      return $false
    }
  }

  Write-host 'Activating Windows...'  
  try{
      $domain=$env:USERDNSDOMAIN
      if($domain){            
        $kmshost = .{
          $x=nslookup -type=srv _vlmcs._tcp.$domain|%{$match=$_ -match 'svr hostname   = (.*)';if($match){return $matches[1]}}
          if($x){
            $x
          }else{
            $y=nslookup -type=srv _vlmcs._tcp|%{$match=$_ -match 'svr hostname   = (.*)';if($match){return $matches[1]}}
            if($y){
              $y
            }else{
              $null
            }
          }
        }
        if ($null -eq $kmshost) {
          write-warning 'No KMS hosts have been found on domain'
          return $false
        }else{
          write-host "KMS server: $kmshost"
          }    
        $osName = (Get-WmiObject -class Win32_OperatingSystem).Caption    
        $osKey=if(!$kmsKey){
            $kmsKeys[$osName]
          }else{
            $kmsKey
          }
        $kmsService = Get-WMIObject -query "select * from SoftwareLicensingService"
        if($osKey){
          $null = $kmsService.InstallProductKey($osKey)
          if ($null -ne ($kmsService | gm -Name SetKeyManagementServiceLookupDomain)) {
              $null = $KMSservice.SetKeyManagementServiceLookupDomain($domain)
          }else{
              $null = $kmsService.SetKeyManagementServiceMachine($kmshost)
              }
          $null = $kmsService.RefreshLicenseStatus()
          return $true
        }else{
          return genericActivation
        }        
      }else{
        return genericActivation
      }
  }catch{
    write-warning $_
    return $false
    }
}          

activateWindowsKms
# Automatic Virtual Machine Activation

function activateWindowsAvma{
    param(
        [string]$guestVm=$env:computername,
        [string][ValidatePattern('^\S{5}-\S{5}-\S{5}-\S{5}-\S{5}$')]$avmaKey
        )
    
    # Currently, this list only consists of Windows Server 2019. Other Windows versions' activation keys can be found here
    # Source: https://docs.microsoft.com/en-us/windows-server/get-started-19/vm-activation-19
    $avmaKeys=@{
        'Microsoft Windows Server 2019 Datacenter'='H3RNG-8C32Q-Q8FRX-6TDXV-WMBMW';
        'Microsoft Windows Server 2019 Standard'='TNK62-RXVTB-4P47B-2D623-4GF74';
        'Microsoft Windows Server 2019 Essentials'='2CTP7-NHT64-BP62M-FV6GG-HFV28';
        }
    $ErrorActionPreference = 'stop'

    function checkActivation($computername=$env:computername){
        $state = Get-WmiObject -Query "Select * from SoftwareLicensingProduct Where PartialProductKey IS NOT NULL AND ApplicationID='55c92734-d682-4d71-983e-d6ec3f16059f'"
        $activationState=Switch ($state.LicenseStatus){
            0 {"Unlicensed"}
            1 {"Licensed"}
            2 {"Out-of-Box Grace Period"}
            3 {"Out-of-Tolerance Grace Period"}
            4 {"Non-Genuine Grace Period"}
            5 {"Notification"}
            6 {"ExtendedGrace"}
        }
        return $activationState
        }

    try{
        $isLocal=$guestVm -match "$env:computername*" -or $guestVm -eq 'localhost'
        if($isLocal){
            try{                
                if(!$avmaKey){
                    $osName=(Get-WmiObject -class Win32_OperatingSystem).Caption
                    $avmaKey=$avmaKeys[$osName]
                    }
                slmgr /ipk $avmaKey;
                #$activationCommand="DISM /online /Set-Edition:$avmaEdition /ProductKey:$avmaKey /AcceptEula"
                #Invoke-Expression $activationCommand
                <# Avoid this error that is caused by mismatching edition with key types                
                #---------------------------
                #Windows Script Host
                #---------------------------
                #Error: 0xC004F069 On a computer running Microsoft Windows non-core edition, run 'slui.exe 0x2a 0xC004F069' to display the error text.
                #
                #
                #---------------------------
                #OK   
                #---------------------------
                #>
                return $(checkActivation)
                }
            catch{
                write-warning "$($error[0])"
                return $false
                }
            }
        elseif ($avmaKey){
            if(!$avmaKey){
                    $osName=(Get-WmiObject -ComputerName $guestVm -class Win32_OperatingSystem).Caption
                    $avmaKey=$avmaKeys[$osName]
                    }
            return invoke-command -ComputerName $guestVm -scriptblock{ param($avmaKey,$checkActivation)
                                                                $ErrorActionPreference = 'stop'
                                                                try{
                                                                    slmgr /ipk $avmaKey;
                                                                    return $([ScriptBlock]::Create($checkActivation).invoke())
                                                                    }
                                                                catch{
                                                                    write-warning "$($error[0])"
                                                                    return $false
                                                                    }
                                                                } -Args $avmaKey,${function:checkActivation}
            }
        else{
            write-warning "No keys are available for activation."
            return $false
            }
        }
    catch{
        write-warning "$($error[0])"
        return $false
        }
}

activateWindowsAvma

Leave a Reply

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