Windows OEM activation script

Windows OEM activation script
Photo by Sunrise King / Unsplash

During an in-place upgrade from Windows 10 to Windows 11, the automatic license transfer doesn’t always seem to work reliably. In my tests, the activation simply didn’t carry over after the upgrade — which, of course, causes unnecessary hassle in day-to-day work.

To save you from doing this manually, I’ve provided a small PowerShell script that applies the license information correctly and activates Windows 11 without any extra effort. Just run it, lean back, and you’re done.

Below is a drop‑in PowerShell script that:

  • Detects if Windows is already licensed — if yes, it exits cleanly.
  • Reads the embedded OEM key from the ACPI MSDM table via WMI (OA3xOriginalProductKey).
  • Installs that key with slmgr /ipk, then activates with slmgr /ato.
  • Writes a simple log to C:\Windows\activate.log.
  • Returns exit code 0 on success; 1 on failure; 2 if no embedded key is found.
Requirements: Run as Administrator. Internet access is required for online activation when using Retail/OEM keys (KMS not used here by design).
<#
.SYNOPSIS
    Activates Windows locally using the embedded OEM product key (ACPI MSDM).

.DESCRIPTION
    - Checks current activation status.
    - Retrieves embedded OEM key from WMI (SoftwareLicensingService.OA3xOriginalProductKey).
    - Installs the key with slmgr.vbs and activates online.
    - Logs to C:\Windows\TWS\activate.log.
    - Exit codes:
        0 = Already licensed or activation succeeded
        1 = Error during activation
        2 = No embedded key found

.NOTES
    Run elevated (as Administrator). 
#>

[CmdletBinding()]
param(
    [switch]$VerboseOutput
)

# --- Helpers ---------------------------------------------------------------

function Write-Log {
    param([string]$Message, [string]$Level = 'INFO')
    $logDir = 'C:\Windows\TWS'
    $logPath = Join-Path $logDir 'activate.log'
    if (-not (Test-Path $logDir)) { New-Item -Path $logDir -ItemType Directory -Force | Out-Null }
    $timestamp = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
    $line = "[$timestamp] [$Level] $Message"
    Add-Content -Path $logPath -Value $line
    if ($VerboseOutput) { Write-Host $line }
}

function Test-Admin {
    $currentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($currentIdentity)
    return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

function Get-ActivationStatus {
    # Windows OS ApplicationID
    $winAppId = '55c92734-d682-4d71-983e-d6ec3f16059f'
    $statusMap = @{
        0 = 'Unlicensed'
        1 = 'Licensed'
        2 = 'OOBGrace'
        3 = 'OOTGrace'
        4 = 'NonGenuineGrace'
        5 = 'Notification'
        6 = 'ExtendedGrace'
    }

    $prod = Get-CimInstance -Namespace root\cimv2 -ClassName SoftwareLicensingProduct `
            -ErrorAction SilentlyContinue |
            Where-Object { $_.ApplicationID -eq $winAppId -and $_.PartialProductKey } |
            Select-Object -First 1

    $status = if ($null -ne $prod) { $statusMap[[int]$prod.LicenseStatus] } else { 'Unknown' }

    [pscustomobject]@{
        StatusName   = $status
        Licensed     = ($status -eq 'Licensed')
        ProductName  = $prod.Name
        Description  = $prod.Description
        PartialKey   = $prod.PartialProductKey
    }
}

function Install-And-ActivateKey {
    param([Parameter(Mandatory)][string]$ProductKey)

    $slmgrPath = Join-Path $env:windir 'System32\slmgr.vbs'
    if (-not (Test-Path $slmgrPath)) {
        throw "slmgr.vbs not found at $slmgrPath"
    }

    $cscript = Join-Path $env:windir 'System32\cscript.exe'

    $run = {
        param($argsLine)
        $psi = New-Object System.Diagnostics.ProcessStartInfo
        $psi.FileName = $cscript
        $psi.Arguments = "//NoLogo `"$slmgrPath`" $argsLine"
        $psi.RedirectStandardOutput = $true
        $psi.RedirectStandardError  = $true
        $psi.UseShellExecute = $false
        $proc = [System.Diagnostics.Process]::Start($psi)
        $stdout = $proc.StandardOutput.ReadToEnd()
        $stderr = $proc.StandardError.ReadToEnd()
        $proc.WaitForExit()
        [pscustomobject]@{
            Args    = $argsLine
            Code    = $proc.ExitCode
            StdOut  = $stdout.Trim()
            StdErr  = $stderr.Trim()
        }
    }

    Write-Log "Installing product key (masked) ..." "INFO"
    $masked = ($ProductKey -replace '(.{5})(?=.)','\$1-') -replace '-$',''
    Write-Log "Key: $masked" "INFO"

    $ipk = & $run "/ipk $ProductKey"
    if ($ipk.StdErr) { Write-Log "slmgr /ipk stderr: $($ipk.StdErr)" "WARN" }
    if ($ipk.StdOut) { Write-Log "slmgr /ipk stdout: $($ipk.StdOut)" "INFO" }

    # Proceed to activation regardless of exit code; we'll verify via WMI
    Write-Log "Attempting online activation ..." "INFO"
    $ato = & $run "/ato"
    if ($ato.StdErr) { Write-Log "slmgr /ato stderr: $($ato.StdErr)" "WARN" }
    if ($ato.StdOut) { Write-Log "slmgr /ato stdout: $($ato.StdOut)" "INFO" }
}

# --- Main -----------------------------------------------------------------

try {
    if (-not (Test-Admin)) {
        Write-Log "Script must be run as Administrator." "ERROR"
        exit 1
    }

    $pre = Get-ActivationStatus
    Write-Log "Pre-check status: $($pre.StatusName); Product: $($pre.ProductName); PartialKey: $($pre.PartialKey)" "INFO"

    if ($pre.Licensed) {
        Write-Log "Windows is already licensed. Nothing to do." "INFO"
        exit 0
    }

    # Read embedded OEM key from WMI
    $svc = Get-CimInstance -Namespace root\cimv2 -ClassName SoftwareLicensingService -ErrorAction SilentlyContinue
    $embeddedKey = $svc.OA3xOriginalProductKey

    if ([string]::IsNullOrWhiteSpace($embeddedKey)) {
        # Optional fallback: BackupProductKeyDefault (not always present/valid)
        try {
            $bk = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform' `
                                   -Name 'BackupProductKeyDefault' -ErrorAction Stop
            if ($bk.BackupProductKeyDefault) {
                Write-Log "No embedded key found; found BackupProductKeyDefault in registry. Using it as a fallback." "WARN"
                $embeddedKey = $bk.BackupProductKeyDefault
            }
        } catch {
            # No fallback. Continue
        }
    }

    if ([string]::IsNullOrWhiteSpace($embeddedKey)) {
        Write-Log "No embedded OEM product key found. Cannot proceed." "ERROR"
        exit 2
    }

    Install-And-ActivateKey -ProductKey $embeddedKey

    Start-Sleep -Seconds 3
    $post = Get-ActivationStatus
    Write-Log "Post-check status: $($post.StatusName); Product: $($post.ProductName); PartialKey: $($post.PartialKey)" "INFO"

    if ($post.Licensed) {
        Write-Log "Activation successful." "INFO"
        exit 0
    } else {
        Write-Log "Activation did not complete successfully." "ERROR"
        exit 1
    }
}
catch {
    Write-Log "Unhandled error: $($_.Exception.Message)" "ERROR"
    exit 1
}