@echo off setlocal EnableExtensions title Windows Key Tool (Optimized) set "WKTOOL_SELF=%~f0" fltmc >nul 2>&1 if not "%ERRORLEVEL%"=="0" ( echo Requesting administrator permission... powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -Verb RunAs -FilePath $env:WKTOOL_SELF" exit /b ) set "WKTOOL_DIR=%TEMP%\WindowsKeyToolOptimized" set "WKTOOL_SCRIPT=%WKTOOL_DIR%\WindowsKeyTool.ps1" if not exist "%WKTOOL_DIR%" mkdir "%WKTOOL_DIR%" >nul 2>&1 powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop'; $marker='### POWERSHELL_SCRIPT_BELOW ###'; $self=$env:WKTOOL_SELF; $out=$env:WKTOOL_SCRIPT; $text=[IO.File]::ReadAllText($self); $idx=$text.LastIndexOf($marker); if($idx -lt 0){ throw 'Embedded PowerShell script marker not found.' }; $script=$text.Substring($idx + $marker.Length).TrimStart([char]13,[char]10); [IO.File]::WriteAllText($out, $script, [Text.Encoding]::ASCII)" if errorlevel 1 ( echo Failed to extract embedded Windows Key Tool script. pause exit /b 1 ) powershell.exe -NoProfile -ExecutionPolicy Bypass -STA -File "%WKTOOL_SCRIPT%" set "WKTOOL_EXIT=%ERRORLEVEL%" del "%WKTOOL_SCRIPT%" >nul 2>&1 exit /b %WKTOOL_EXIT% ### POWERSHELL_SCRIPT_BELOW ### # Windows Key Tool (Optimized) # Same WMI-only logic as the original. Optimizations: # O1 Parallel TCP probe (deadline-based, single wait loop) # O2 slmgr /ato timeout reduced to 60s # O3 Skip fixed 450ms sleep after InstallKey (poll instead) # O4 Cache Win32_OperatingSystem + Win32 licensing info in the GUI # O5 Run w32tm + netsh probes in parallel via thread jobs # O6 Poll sppsvc status with 50ms cadence up to 1s Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' # ============================================================ # BENCHMARK HARNESS # ============================================================ $script:BenchResults = New-Object System.Collections.Generic.List[object] function Start-Bench { param([string]$Name) return [pscustomobject]@{ Name = $Name Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() } } function Stop-Bench { param([object]$Bench) $Bench.Stopwatch.Stop() $entry = [pscustomobject]@{ Name = $Bench.Name ElapsedMs = [int64]$Bench.Stopwatch.ElapsedMilliseconds Timestamp = (Get-Date).ToString('HH:mm:ss.fff') } $script:BenchResults.Add($entry) Write-Host ("[BENCH] {0,-32} {1,6} ms" -f $entry.Name, $entry.ElapsedMs) return $entry } function Export-Bench { param([string]$Path) $script:BenchResults | Export-Csv -Path $Path -NoTypeInformation -Encoding UTF8 Write-Host ("[BENCH] Exported {0} entries to {1}" -f $script:BenchResults.Count, $Path) } # ============================================================ # ORIGINAL CODE (lightly trimmed) + OPTIMIZATIONS # ============================================================ function Test-IsWindows { return [System.Environment]::OSVersion.Platform -eq [System.PlatformID]::Win32NT } function Test-IsAdministrator { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal -ArgumentList $identity return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function Start-SelfElevated { $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = 'powershell.exe' $psi.Arguments = ('-NoProfile -ExecutionPolicy Bypass -STA -File "{0}"' -f $PSCommandPath) $psi.Verb = 'runas' [System.Diagnostics.Process]::Start($psi) | Out-Null } if (-not (Test-IsWindows)) { Write-Host 'This tool runs on Windows only.' exit 1 } if (-not (Test-IsAdministrator)) { try { Start-SelfElevated } catch { Write-Host 'Administrator permission is required.' Write-Host $_.Exception.Message pause } exit } Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing [System.Windows.Forms.Application]::EnableVisualStyles() $script:WindowsApplicationId = '55c92734-d682-4d71-983e-d6ec3f16059f' $script:LastDiagnostics = '' $script:LastConnectivityText = '' function Normalize-ActivationCode { param([string]$Code) if ([string]::IsNullOrWhiteSpace($Code)) { return '' } $text = $Code.Trim() if ($text -match '0x([0-9A-Fa-f]{8})') { return ('0x{0}' -f $matches[1].ToUpperInvariant()) } if ($text -match '^ExitCode\s+-?\d+$') { return $text } return $text } $script:ActivationIssueCatalog = @{} $script:ErrorHints = @{} $script:LastActivationSummary = '' function Add-ActivationIssue { param( [string[]]$Codes, [string]$Title, [string]$Meaning, [string]$Action, [string]$Category = 'General', [string]$Severity = 'Error', [bool]$Retry = $false, [bool]$OpenSettings = $true, [bool]$Phone = $false, [string[]]$AutoFix = @(), [bool]$HardStop = $false, [bool]$ManualResolve = $false, [string]$ManualAction = '', [string[]]$ManualSteps = @() ) foreach ($code in $Codes) { $normalized = Normalize-ActivationCode $code if ([string]::IsNullOrWhiteSpace($normalized)) { continue } $issue = [pscustomobject]@{ Code = $normalized Title = $Title Meaning = $Meaning Action = $Action Category = $Category Severity = $Severity Retry = $Retry OpenSettings = $OpenSettings Phone = $Phone AutoFix = $AutoFix HardStop = $HardStop ManualResolve = $ManualResolve ManualAction = $ManualAction ManualSteps = $ManualSteps } $script:ActivationIssueCatalog[$normalized] = $issue $script:ErrorHints[$normalized] = ('{0} Next: {1}' -f $Meaning, $Action) } } Add-ActivationIssue -Codes @('0x00000000') -Title 'Activation succeeded' -Meaning 'Windows reported success.' -Action 'Refresh activation status and confirm Windows shows Licensed.' -Category 'Success' -Severity 'Info' -OpenSettings $false Add-ActivationIssue -Codes @('0x803F7001','0x800704CF','0xC004F213','0xC004F014') -Title 'No valid license or key installed' -Meaning 'Windows could not find a valid license or an installed product key for this device.' -Action 'Enter a genuine 25-character key that belongs to this device, or open Activation Settings and use the troubleshooter/Microsoft Store path.' -Category 'License' -OpenSettings $true -HardStop $true Add-ActivationIssue -Codes @('0xC004C060','0xC004C4A2','0x803FA067','0xC004C001','0xC004C004','0xC004F004','0xC004C007','0xC004F005','0xC004C00F','0xC004C010','0xC004C00E','0xC004C4A4','0xC004C4A5','0xC004B001','0xC004F010','0xC004F050','0x80070490') -Title 'Product key cannot be used' -Meaning 'The product key is invalid, mistyped, blocked for this install, or not accepted by the installed Windows version.' -Action 'Recheck the 25-character key, confirm edition and channel, then use a different valid Retail/OEM/MAK key if Windows still rejects it.' -Category 'ProductKey' -HardStop $true Add-ActivationIssue -Codes @('0xC004C003','0xC004F051','0xC004B100') -Title 'Product key blocked or unsupported' -Meaning 'The activation server rejected this key as blocked, unsupported, or not valid for the current license channel.' -Action 'Use another genuine key or contact the seller, device maker, or Microsoft/licensing admin for replacement.' -Category 'ProductKey' -HardStop $true Add-ActivationIssue -Codes @('0xC004C008') -Title 'Manual phone activation required' -Meaning 'The activation server says this key was already used on another device or exceeded the allowed online unlock count. If the license is valid for this PC or was moved after a hardware change, manual activation can still resolve it.' -Action 'The tool gets the Installation ID with slmgr /dti, copies/types it into the official phone/portal flow, watches clipboard for the Confirmation ID, then applies it with slmgr /atp.' -Category 'Manual' -Phone $true -ManualResolve $true -ManualAction 'Use slmgr /dti to collect Installation ID, let the user complete Microsoft puzzle/sign-in, type Installation ID, auto-detect Confirmation ID from clipboard, then run slmgr /atp and refresh status.' -ManualSteps @('Confirm the key belongs to this PC or is transferable under the license terms.','Tool runs slmgr /dti and copies the 9 Installation ID groups to clipboard.','Tool opens Activation Settings, SLUI 04 phone activation, and Microsoft Product Activation portal.','Complete Microsoft security puzzle/CAPTCHA and Microsoft account sign-in manually when requested.','Use Type IID after focusing the first Installation ID field; the tool types all 9 groups with Tab between fields.','Copy the Confirmation ID from Microsoft; the tool auto-detects 48 digits from clipboard.','Tool auto-applies the Confirmation ID with slmgr /atp, refreshes status, and confirms Licensed.') Add-ActivationIssue -Codes @('0xC004C020','0xC004C021') -Title 'Activation limit exceeded' -Meaning 'The activation server reports that this MAK key has reached its allowed activation count.' -Action 'Use another valid key or contact the organization/Microsoft Licensing Activation Center to increase or replace the activation allowance.' -Category 'Limit' -Phone $true -HardStop $true Add-ActivationIssue -Codes @('0xC004F034','0xC004F069','0xC004F210','0xC004F212','0xC004E016','0xC004F00F','0xC004F035') -Title 'Edition or license channel mismatch' -Meaning 'The key does not match the installed Windows edition, version, hardware binding, or license channel.' -Action 'Compare the installed EditionID with the key type. Use the Home-to-Pro button for Pro upgrades from Home, or reinstall/repair to the edition that matches the license.' -Category 'Edition' -OpenSettings $true -Phone $true -HardStop $true Add-ActivationIssue -Codes @('0xC004F211') -Title 'Hardware changed' -Meaning 'Windows reports a significant hardware change and cannot match the previous digital license automatically.' -Action 'Open Activation Settings, run Troubleshoot, then use the reactivation-after-hardware-change flow or enter a valid transferable product key.' -Category 'Hardware' -OpenSettings $true -Phone $true -HardStop $true Add-ActivationIssue -Codes @('0x80072F8F','0x80072EE2','0x80072EFE','0xC004FC03','0x87E10BC6') -Title 'Online activation connectivity problem' -Meaning 'Windows could not verify the key online because of date/time, TLS, proxy, firewall, DNS, Microsoft service, or internet connectivity.' -Action 'The tool starts sppsvc/w32time, resyncs time, flushes DNS, reruns connectivity checks, refreshes license status, then retries activation once.' -Category 'Connectivity' -Retry $true -OpenSettings $true -Phone $true -AutoFix @('ServiceRefresh','TimeSync','DnsFlush','ConnectivityCheck','LicenseRefresh') Add-ActivationIssue -Codes @('0xC004E028','0x80070652') -Title 'Activation or update already in progress' -Meaning 'Windows is already processing activation or another install/update operation is still running.' -Action 'The tool waits, refreshes sppsvc/licensing state, then retries activation once.' -Category 'Busy' -Retry $true -OpenSettings $false -AutoFix @('Wait','ServiceRefresh','LicenseRefresh') Add-ActivationIssue -Codes @('0x8007232B','0x8007232A','0x8007251D','0x80092328','0x8007007B','0xC004F074','0xC004F038','0xC004F039','0xC004F041','0xC004F042','0xC004F06C','0x800706BA') -Title 'KMS or DNS activation path failed' -Meaning 'Windows is trying a volume/KMS activation path but cannot reach a valid KMS service, DNS SRV record, RPC path, or time-synced KMS host.' -Action 'The tool refreshes service/time/DNS/connectivity and retries once. If it still fails, use a Retail/OEM/MAK key or connect to the organization VPN/domain KMS path.' -Category 'KMS' -Retry $true -OpenSettings $true -AutoFix @('ServiceRefresh','TimeSync','DnsFlush','ConnectivityCheck','LicenseRefresh') Add-ActivationIssue -Codes @('0x80070005') -Title 'Access denied' -Meaning 'The activation action needs elevated permission or is blocked by policy/security controls.' -Action 'Run the tool as administrator, confirm UAC, and check endpoint security or group policy if the elevated tool still fails.' -Category 'Permission' -OpenSettings $false -HardStop $true Add-ActivationIssue -Codes @('0xC004F009','0xC004E003','0x80004005','0x80131500') -Title 'Licensing service or system state problem' -Meaning 'Windows licensing returned a generic, damaged-state, expired-grace, or wrapper error.' -Action 'The tool refreshes sppsvc/licensing state and retries once. If it still fails, reboot, run Windows Update and Activation Troubleshooter, then copy diagnostics.' -Category 'System' -Retry $true -OpenSettings $true -AutoFix @('ServiceRefresh','LicenseRefresh','Wait') Add-ActivationIssue -Codes @('0xC004F02C') -Title 'Phone activation data invalid' -Meaning 'Windows reports the offline/phone activation confirmation data is not valid.' -Action 'Restart the phone activation flow, confirm the Installation ID and Confirmation ID, then retry.' -Category 'Phone' -OpenSettings $true -Phone $true -HardStop $true function Format-HResult { param([object]$Value) if ($null -eq $Value) { return $null } if ($Value -is [string]) { if ($Value -match '0x([0-9A-Fa-f]{8})') { return ('0x{0}' -f $matches[1].ToUpperInvariant()) } return $Value } try { if ($Value -is [uint32]) { return ('0x{0:X8}' -f $Value) } $asInt64 = [int64]$Value if ($asInt64 -lt 0) { $asUInt32 = [BitConverter]::ToUInt32([BitConverter]::GetBytes([int32]$asInt64), 0) return ('0x{0:X8}' -f $asUInt32) } return ('0x{0:X8}' -f ([uint32]$asInt64)) } catch { return ([string]$Value) } } function Get-ErrorHint { param([string]$Code) if ([string]::IsNullOrWhiteSpace($Code)) { return '' } $issue = Get-ActivationIssue $Code return ('{0} Next: {1}' -f $issue.Meaning, $issue.Action) } function Get-ActivationIssue { param([string]$Code) $normalized = Normalize-ActivationCode $Code if (-not [string]::IsNullOrWhiteSpace($normalized) -and $script:ActivationIssueCatalog.ContainsKey($normalized)) { return $script:ActivationIssueCatalog[$normalized] } if ($normalized -like 'ExitCode *') { return [pscustomobject]@{ Code = $normalized Title = 'Activation command failed' Meaning = 'The Windows activation command returned a non-zero process exit code without a known activation HRESULT.' Action = 'Review the command output, refresh license status, then run Activation Settings or copy diagnostics for support.' Category = 'Process' Severity = 'Error' Retry = $true OpenSettings = $true Phone = $false AutoFix = @('ServiceRefresh','LicenseRefresh') HardStop = $false ManualResolve = $false ManualAction = '' ManualSteps = @() } } return [pscustomobject]@{ Code = $normalized Title = 'Unknown activation code' Meaning = 'The tool does not have a specific rule for this activation code yet.' Action = 'Copy diagnostics, check the new code in Microsoft activation support, and try Activation Settings/Troubleshooter.' Category = 'Unknown' Severity = 'Warning' Retry = $false OpenSettings = $true Phone = $false AutoFix = @() HardStop = $false ManualResolve = $false ManualAction = '' ManualSteps = @() } } function New-ActivationResponse { param( [string]$Phase, [bool]$Success, [string]$Code, [string]$Message ) $normalized = Normalize-ActivationCode $Code if ($Success -and [string]::IsNullOrWhiteSpace($normalized)) { $normalized = '0x00000000' } $issue = Get-ActivationIssue $normalized $text = if ([string]::IsNullOrWhiteSpace($Message)) { $issue.Meaning } else { $Message } return [pscustomobject]@{ Phase = $Phase Success = $Success Code = $normalized Title = $issue.Title Category = $issue.Category Severity = $issue.Severity Message = $text Meaning = $issue.Meaning Guidance = $issue.Action Retry = [bool]$issue.Retry OpenSettings = [bool]$issue.OpenSettings Phone = [bool]$issue.Phone AutoFix = @($issue.AutoFix) HardStop = [bool]$issue.HardStop ManualResolve = [bool]$issue.ManualResolve ManualAction = [string]$issue.ManualAction ManualSteps = @($issue.ManualSteps) } } function Format-ActivationResponseForLog { param([object]$Response) if ($null -eq $Response) { return '' } $code = if ([string]::IsNullOrWhiteSpace($Response.Code)) { 'no-code' } else { $Response.Code } return ('{0}: {1} - {2}. {3}' -f $Response.Phase, $code, $Response.Title, $Response.Guidance) } function Get-ReturnCode { param([object]$Result) if ($null -eq $Result) { return [uint32]0 }; $property = $Result.PSObject.Properties | Where-Object { $_.Name -eq 'ReturnValue' } | Select-Object -First 1; if ($null -eq $property) { return [uint32]0 }; return [uint32]$property.Value } function Get-ExceptionCode { param([System.Management.Automation.ErrorRecord]$Record) $message = $Record.Exception.Message; if ($message -match '0x([0-9A-Fa-f]{8})') { return ('0x{0}' -f $matches[1].ToUpperInvariant()) }; if ($Record.Exception.HResult -ne 0) { return (Format-HResult $Record.Exception.HResult) }; return $null } function Get-LicenseStatusName { param([object]$Code) if ($null -eq $Code) { return 'Unknown' } switch ([int]$Code) { 0 { return 'Unlicensed' } 1 { return 'Licensed' } 2 { return 'OOB grace' } 3 { return 'OOT grace' } 4 { return 'Non-genuine grace' } 5 { return 'Notification' } 6 { return 'Extended grace' } default { return ('Unknown ({0})' -f $Code) } } } function Test-HomeEdition { param([string]$EditionId) if ([string]::IsNullOrWhiteSpace($EditionId)) { return $false }; return ($EditionId -match '^(Core|CoreSingleLanguage|CoreCountrySpecific|Starter|Home)') } function Format-ProductKey { param([string]$Text) if ([string]::IsNullOrEmpty($Text)) { return '' } $raw = (($Text.ToUpperInvariant()) -replace '[^A-Z0-9]', '') if ($raw.Length -gt 25) { $raw = $raw.Substring(0, 25) } $parts = New-Object System.Collections.Generic.List[string] for ($i = 0; $i -lt $raw.Length; $i += 5) { $length = [Math]::Min(5, $raw.Length - $i); $parts.Add($raw.Substring($i, $length)) } return ($parts -join '-') } function Get-ProductKeyValidation { param([string]$Text) $formatted = Format-ProductKey $Text $raw = ($formatted -replace '-', '') $valid = ($formatted -match '^[A-Z0-9]{5}(-[A-Z0-9]{5}){4}$') $last5 = '' if ($raw.Length -ge 5) { $last5 = $raw.Substring($raw.Length - 5, 5) } return [pscustomobject]@{ Valid = $valid; Key = $formatted; Last5 = $last5 } } function Clear-ProductKeyInput { $controlVariable = Get-Variable -Name KeyTextBox -Scope Script -ErrorAction SilentlyContinue if ($null -ne $controlVariable -and $null -ne $controlVariable.Value) { $controlVariable.Value.Clear() } [System.GC]::Collect() } function Set-ClipboardText { param([string]$Text) try { [System.Windows.Forms.Clipboard]::SetText($Text) } catch { Set-Clipboard -Value $Text } } function Invoke-ProcessCapture { param([string]$FileName, [string]$Arguments, [int]$TimeoutSeconds = 120) $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $FileName; $psi.Arguments = $Arguments $psi.UseShellExecute = $false; $psi.RedirectStandardOutput = $true; $psi.RedirectStandardError = $true; $psi.CreateNoWindow = $true $process = New-Object System.Diagnostics.Process; $process.StartInfo = $psi [void]$process.Start() $finished = $process.WaitForExit($TimeoutSeconds * 1000) if (-not $finished) { try { $process.Kill() } catch { }; return [pscustomobject]@{ ExitCode = -1; Output = 'Timed out.'; Error = ''; TimedOut = $true } } return [pscustomobject]@{ ExitCode = $process.ExitCode; Output = $process.StandardOutput.ReadToEnd(); Error = $process.StandardError.ReadToEnd(); TimedOut = $false } } function Get-FirstUsefulLine { param([string]$Text) if ([string]::IsNullOrWhiteSpace($Text)) { return '' }; $line = @($Text -split "(`r`n|`n|`r)" | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -First 1); if ($line.Count -eq 0) { return '' }; return [string]$line[0] } # ============================================================ # OPTIMIZATION O1: Parallel TCP probe (deadline-based) # ============================================================ function Test-TcpTargets { param([object[]]$Targets, [int]$TimeoutMs = 900) $bench = Start-Bench 'TCP-Probe' $probes = New-Object System.Collections.Generic.List[object] foreach ($target in $Targets) { $client = $null try { $hostName = [string]$target.Host $port = [int]$target.Port $client = New-Object System.Net.Sockets.TcpClient $async = $client.BeginConnect($hostName, $port, $null, $null) $probes.Add([pscustomobject]@{ Host = $hostName; Port = $port; Client = $client; Async = $async; Started = $true }) } catch { if ($null -ne $client) { $client.Close() } $probes.Add([pscustomobject]@{ Host = [string]$target.Host; Port = [int]$target.Port; Client = $null; Async = $null; Started = $false }) } } $deadline = (Get-Date).AddMilliseconds($TimeoutMs) $results = New-Object System.Collections.Generic.List[object] # Single deadline loop instead of per-host WaitOne (O1) foreach ($probe in $probes) { $ok = $false try { if ($probe.Started -and $null -ne $probe.Async) { $remaining = [Math]::Max(0, [int](($deadline - (Get-Date)).TotalMilliseconds)) if ($probe.Async.AsyncWaitHandle.WaitOne($remaining, $false)) { $probe.Client.EndConnect($probe.Async) $ok = $probe.Client.Connected } } } catch { $ok = $false } finally { if ($null -ne $probe.Client) { $probe.Client.Close() } } $results.Add([pscustomobject]@{ Host = $probe.Host; Port = $probe.Port; Success = $ok }) } Stop-Bench $bench | Out-Null return $results.ToArray() } function New-CheckResult { param([string]$Name, [string]$Status, [string]$Detail) return [pscustomobject]@{ Name = $Name; Status = $Status; Detail = $Detail } } # ============================================================ # OPTIMIZATION O5: Run w32tm + netsh in parallel via jobs # ============================================================ function Invoke-SystemProbesParallel { $bench = Start-Bench 'System-Probes' $jobs = @() $jobs += Start-Job -ScriptBlock { try { $w32 = & (Join-Path $env:windir 'System32\w32tm.exe') '/query /status' 2>$null if ($LASTEXITCODE -eq 0) { return @{ Ok = $true; Line = ($w32 | Select-Object -First 1) } } else { return @{ Ok = $false; Line = 'Could not query w32time. Incorrect date/time can break TLS activation.' } } } catch { return @{ Ok = $false; Line = $_.Exception.Message } } } $jobs += Start-Job -ScriptBlock { try { $netsh = & (Join-Path $env:windir 'System32\netsh.exe') 'winhttp' 'show' 'proxy' 2>$null $detail = ($netsh | Where-Object { $_ -and $_.Trim() } | Select-Object -First 1) if (-not $detail) { $detail = 'No WinHTTP proxy detail returned.' } return @{ Ok = $true; Line = $detail } } catch { return @{ Ok = $false; Line = $_.Exception.Message } } } $w32Result = $jobs[0] | Wait-Job | Receive-Job $netshResult = $jobs[1] | Wait-Job | Receive-Job $jobs | Remove-Job | Out-Null Stop-Bench $bench | Out-Null return [pscustomobject]@{ W32Time = $w32Result; WinHttpProxy = $netshResult } } function Invoke-ConnectivityChecks { $bench = Start-Bench 'Connectivity-Checks' $results = New-Object System.Collections.Generic.List[object] try { $service = Get-Service -Name sppsvc -ErrorAction Stop if ($service.Status -ne 'Running') { try { Start-Service -Name sppsvc -ErrorAction Stop; Start-Sleep -Milliseconds 250; $service.Refresh() } catch { } } if ($service.Status -eq 'Running') { $results.Add((New-CheckResult 'Software Protection Service' 'OK' 'sppsvc is running.')) } else { $results.Add((New-CheckResult 'Software Protection Service' 'FAIL' ('sppsvc status is {0}.' -f $service.Status))) } } catch { $results.Add((New-CheckResult 'Software Protection Service' 'FAIL' $_.Exception.Message)) } # O5: parallel w32tm + netsh $sysProbes = Invoke-SystemProbesParallel $w32Status = if ($sysProbes.W32Time.Ok) { 'OK' } else { 'WARN' } $results.Add((New-CheckResult 'Windows Time' $w32Status ([string]$sysProbes.W32Time.Line))) $results.Add((New-CheckResult 'WinHTTP Proxy' 'INFO' ([string]$sysProbes.WinHttpProxy.Line))) $hosts = @( [pscustomobject]@{ Host = 'activation.sls.microsoft.com'; Port = 443 }, [pscustomobject]@{ Host = 'validation.sls.microsoft.com'; Port = 443 }, [pscustomobject]@{ Host = 'activation-v2.sls.microsoft.com'; Port = 443 }, [pscustomobject]@{ Host = 'validation-v2.sls.microsoft.com'; Port = 443 }, [pscustomobject]@{ Host = 'www.microsoft.com'; Port = 443 }, [pscustomobject]@{ Host = 'crl.microsoft.com'; Port = 80 } ) $slsReachable = $false $tcpResults = Test-TcpTargets -Targets $hosts -TimeoutMs 900 foreach ($tcpResult in $tcpResults) { $hostName = [string]$tcpResult.Host; $port = [int]$tcpResult.Port; $ok = [bool]$tcpResult.Success if ($ok -and $hostName -like '*sls.microsoft.com') { $slsReachable = $true } $tcpStatus = if ($ok) { 'OK' } else { 'FAIL' } $tcpDetail = if ($ok) { 'Connected.' } else { 'Could not connect.' } $results.Add((New-CheckResult ('TCP {0} {1}' -f $port, $hostName) $tcpStatus $tcpDetail)) } if ($slsReachable) { $results.Add((New-CheckResult 'Activation endpoint reachability' 'OK' 'At least one Microsoft SLS activation endpoint accepted TCP 443.')) } else { $results.Add((New-CheckResult 'Activation endpoint reachability' 'FAIL' 'No tested Microsoft SLS activation endpoint accepted TCP 443. Check DNS, firewall, proxy, TLS inspection, and captive portal.')) } $blockingFailures = @($results | Where-Object { $_.Status -eq 'FAIL' -and ($_.Name -eq 'Software Protection Service' -or $_.Name -eq 'Activation endpoint reachability') }) $text = ($results | ForEach-Object { ('[{0}] {1}: {2}' -f $_.Status, $_.Name, $_.Detail) }) -join "`r`n" $script:LastConnectivityText = $text Stop-Bench $bench | Out-Null return [pscustomobject]@{ Results = $results; Text = $text; HasBlockingFailures = ($blockingFailures.Count -gt 0) } } # ============================================================ # OPTIMIZATION O6: Fast sppsvc poll (50ms cadence, 1s cap) # ============================================================ function Ensure-SoftwareProtectionService { $bench = Start-Bench 'Ensure-sppsvc' try { $service = Get-Service -Name sppsvc -ErrorAction Stop if ($service.Status -ne 'Running') { Start-Service -Name sppsvc -ErrorAction Stop $deadline = (Get-Date).AddSeconds(1) while ((Get-Date) -lt $deadline -and $service.Status -ne 'Running') { Start-Sleep -Milliseconds 50 $service.Refresh() } } $service.Refresh() Stop-Bench $bench | Out-Null return [pscustomobject]@{ Success = ($service.Status -eq 'Running'); Message = ('sppsvc status: {0}' -f $service.Status) } } catch { Stop-Bench $bench | Out-Null return [pscustomobject]@{ Success = $false; Message = $_.Exception.Message } } } # ============================================================ # OPTIMIZATION O4: Cached Windows info # ============================================================ $script:CachedWindowsInfo = $null function Get-WindowsInfo { if ($null -ne $script:CachedWindowsInfo) { return $script:CachedWindowsInfo } $os = Get-CimInstance -ClassName Win32_OperatingSystem $cv = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' $ubr = '' if ($cv.PSObject.Properties.Name -contains 'UBR') { $ubr = ".$($cv.UBR)" } $displayVersion = '' if ($cv.PSObject.Properties.Name -contains 'DisplayVersion') { $displayVersion = [string]$cv.DisplayVersion } elseif ($cv.PSObject.Properties.Name -contains 'ReleaseId') { $displayVersion = [string]$cv.ReleaseId } $script:CachedWindowsInfo = [pscustomobject]@{ Caption = [string]$os.Caption EditionId = [string]$cv.EditionID DisplayVersion = $displayVersion Build = ('{0}{1}' -f $cv.CurrentBuild, $ubr) Architecture = [string]$os.OSArchitecture } return $script:CachedWindowsInfo } function Get-WindowsLicenseProduct { param([string]$PartialKey) $items = @(Get-CimInstance -ClassName SoftwareLicensingProduct -Filter "ApplicationID='$script:WindowsApplicationId'" | Where-Object { $_.Name -like 'Windows*' }) if ($items.Count -eq 0) { return $null } if (-not [string]::IsNullOrWhiteSpace($PartialKey)) { $matched = @($items | Where-Object { $_.PartialProductKey -eq $PartialKey }) if ($matched.Count -gt 0) { return $matched[0] } } $licensed = @($items | Where-Object { $_.PartialProductKey -and $_.LicenseStatus -eq 1 }) if ($licensed.Count -gt 0) { return $licensed[0] } $withKey = @($items | Where-Object { $_.PartialProductKey }) if ($withKey.Count -gt 0) { return $withKey[0] } return $items[0] } function Get-LicenseSnapshot { param([string]$PartialKey) try { $product = Get-WindowsLicenseProduct -PartialKey $PartialKey if ($null -eq $product) { return [pscustomobject]@{ Status = 'Unknown'; Reason = ''; Hint = '' } } $reason = Format-HResult $product.LicenseStatusReason return [pscustomobject]@{ Status = (Get-LicenseStatusName $product.LicenseStatus); Reason = $reason; Hint = (Get-ErrorHint $reason) } } catch { return [pscustomobject]@{ Status = 'Unknown'; Reason = ''; Hint = $_.Exception.Message } } } function Add-LicenseSnapshotToResponse { param([object]$Response, [object]$Snapshot) if ($null -eq $Response) { return $null } $status = if ($null -eq $Snapshot) { 'Unknown' } else { [string]$Snapshot.Status } $reason = if ($null -eq $Snapshot) { '' } else { [string]$Snapshot.Reason } $hint = if ($null -eq $Snapshot) { '' } else { [string]$Snapshot.Hint } $Response | Add-Member -NotePropertyName LicenseStatus -NotePropertyValue $status -Force $Response | Add-Member -NotePropertyName LicenseReason -NotePropertyValue $reason -Force $Response | Add-Member -NotePropertyName LicenseHint -NotePropertyValue $hint -Force return $Response } function Wait-LicenseProductByPartialKey { param([string]$PartialKey, [int]$TimeoutMs = 1800) if ([string]::IsNullOrWhiteSpace($PartialKey)) { return $null } $deadline = (Get-Date).AddMilliseconds($TimeoutMs) do { $product = Get-WindowsLicenseProduct -PartialKey $PartialKey if ($null -ne $product -and $product.PartialProductKey -eq $PartialKey) { return $product } Start-Sleep -Milliseconds 120 Invoke-RefreshLicenseStatus } while ((Get-Date) -lt $deadline) return Get-WindowsLicenseProduct -PartialKey $PartialKey } function Invoke-InstallProductKey { param([string]$ProductKey) $bench = Start-Bench 'Install-ProductKey' try { $service = Get-CimInstance -ClassName SoftwareLicensingService $result = Invoke-CimMethod -InputObject $service -MethodName InstallProductKey -Arguments @{ ProductKey = $ProductKey } $code = Get-ReturnCode $result $formatted = Format-HResult $code Stop-Bench $bench | Out-Null return (New-ActivationResponse -Phase 'Install product key' -Success ($code -eq 0) -Code $formatted -Message (Get-ErrorHint $formatted)) } catch { $code = Get-ExceptionCode $_ Stop-Bench $bench | Out-Null return (New-ActivationResponse -Phase 'Install product key' -Success $false -Code $code -Message ($_.Exception.Message + "`r`n" + (Get-ErrorHint $code))) } } function Invoke-RefreshLicenseStatus { try { $service = Get-CimInstance -ClassName SoftwareLicensingService; Invoke-CimMethod -InputObject $service -MethodName RefreshLicenseStatus | Out-Null } catch { } } function Invoke-ActivateWindows { param([string]$PartialKey) $bench = Start-Bench 'Activate-WMI' try { Invoke-RefreshLicenseStatus $product = Wait-LicenseProductByPartialKey -PartialKey $PartialKey -TimeoutMs 1800 if ($null -eq $product) { Stop-Bench $bench | Out-Null $response = New-ActivationResponse -Phase 'WMI activation' -Success $false -Code '0xC004F213' -Message 'Could not find a Windows licensing product to activate after installing the key.' return (Add-LicenseSnapshotToResponse -Response $response -Snapshot (Get-LicenseSnapshot -PartialKey $PartialKey)) } $result = Invoke-CimMethod -InputObject $product -MethodName Activate $code = Get-ReturnCode $result Invoke-RefreshLicenseStatus $snapshot = Get-LicenseSnapshot -PartialKey $PartialKey $formatted = Format-HResult $code $success = (($code -eq 0) -or ($snapshot.Status -eq 'Licensed')) Stop-Bench $bench | Out-Null $response = New-ActivationResponse -Phase 'WMI activation' -Success $success -Code $formatted -Message (Get-ErrorHint $formatted) return (Add-LicenseSnapshotToResponse -Response $response -Snapshot $snapshot) } catch { $code = Get-ExceptionCode $_ $snapshot = Get-LicenseSnapshot -PartialKey $PartialKey Stop-Bench $bench | Out-Null $response = New-ActivationResponse -Phase 'WMI activation' -Success $false -Code $code -Message ($_.Exception.Message + "`r`n" + (Get-ErrorHint $code)) return (Add-LicenseSnapshotToResponse -Response $response -Snapshot $snapshot) } } # ============================================================ # OPTIMIZATION O2: slmgr /ato timeout 180s -> 60s # ============================================================ function Invoke-SlmgrActivate { param([string]$PartialKey) $bench = Start-Bench 'Activate-slmgr' try { $scriptPath = Join-Path $env:windir 'System32\slmgr.vbs' $cscriptPath = Join-Path $env:windir 'System32\cscript.exe' # O2: was 180s, now 60s $result = Invoke-ProcessCapture -FileName $cscriptPath -Arguments ('//nologo "{0}" /ato' -f $scriptPath) -TimeoutSeconds 60 Invoke-RefreshLicenseStatus $snapshot = Get-LicenseSnapshot -PartialKey $PartialKey $text = (($result.Output + "`r`n" + $result.Error).Trim()) $code = '' if ($text -match '0x([0-9A-Fa-f]{8})') { $code = ('0x{0}' -f $matches[1].ToUpperInvariant()) } elseif (-not [string]::IsNullOrWhiteSpace($snapshot.Reason)) { $code = $snapshot.Reason } elseif ($result.ExitCode -ne 0) { $code = ('ExitCode {0}' -f $result.ExitCode) } else { $code = '0x00000000' } $message = if (-not [string]::IsNullOrWhiteSpace($text)) { $text } else { Get-ErrorHint $code } Stop-Bench $bench | Out-Null $response = New-ActivationResponse -Phase 'slmgr activation' -Success ($snapshot.Status -eq 'Licensed') -Code $code -Message $message return (Add-LicenseSnapshotToResponse -Response $response -Snapshot $snapshot) } catch { $code = Get-ExceptionCode $_ Stop-Bench $bench | Out-Null $response = New-ActivationResponse -Phase 'slmgr activation' -Success $false -Code $code -Message ($_.Exception.Message + "`r`n" + (Get-ErrorHint $code)) return (Add-LicenseSnapshotToResponse -Response $response -Snapshot ([pscustomobject]@{ Status = 'Unknown'; Reason = ''; Hint = '' })) } } function Get-DiagnosticsText { $info = Get-WindowsInfo $license = Get-WindowsLicenseProduct -PartialKey '' $licenseStatus = 'Unknown'; $reason = ''; $partial = ''; $name = ''; $description = '' if ($null -ne $license) { $licenseStatus = Get-LicenseStatusName $license.LicenseStatus $reason = Format-HResult $license.LicenseStatusReason $partial = [string]$license.PartialProductKey $name = [string]$license.Name $description = [string]$license.Description } $connectivityText = if ([string]::IsNullOrWhiteSpace($script:LastConnectivityText)) { 'Not run in this session.' } else { $script:LastConnectivityText } $activationText = if ([string]::IsNullOrWhiteSpace($script:LastActivationSummary)) { 'No activation attempt recorded in this session.' } else { $script:LastActivationSummary } return @('Windows Key Tool diagnostics', ('Time: {0}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')), ('Windows: {0}' -f $info.Caption), ('EditionID: {0}' -f $info.EditionId), ('Version: {0}' -f $info.DisplayVersion), ('Build: {0}' -f $info.Build), ('Architecture: {0}' -f $info.Architecture), ('Activation status: {0}' -f $licenseStatus), ('License status reason: {0}' -f $reason), ('Installed key last 5: {0}' -f $partial), ('License product: {0}' -f $name), ('License description: {0}' -f $description), '', 'Last activation attempt:', $activationText, '', 'Last connectivity check:', $connectivityText) -join "`r`n" } function Append-Log { param([string]$Text) $timestamp = Get-Date -Format 'HH:mm:ss'; $script:LogBox.AppendText(('[{0}] {1}{2}' -f $timestamp, $Text, [Environment]::NewLine)); [System.Windows.Forms.Application]::DoEvents() } function Set-Busy { param([bool]$Busy) $script:Form.Cursor = if ($Busy) { [System.Windows.Forms.Cursors]::WaitCursor } else { [System.Windows.Forms.Cursors]::Default }; $script:ActivateButton.Enabled = -not $Busy; $script:HomeProButton.Enabled = (-not $Busy) -and $script:IsHomeEdition; $script:RefreshButton.Enabled = -not $Busy; $script:SettingsButton.Enabled = -not $Busy; $script:CheckButton.Enabled = -not $Busy; $script:PreflightCheckBox.Enabled = -not $Busy; $script:FallbackCheckBox.Enabled = -not $Busy; $script:BenchButton.Enabled = -not $Busy; [System.Windows.Forms.Application]::DoEvents() } function Update-SystemInfo { try { $info = Get-WindowsInfo $license = Get-WindowsLicenseProduct -PartialKey '' $script:IsHomeEdition = Test-HomeEdition $info.EditionId $script:WindowsValueLabel.Text = ('{0} | {1} | Build {2}' -f $info.Caption, $info.Architecture, $info.Build) $script:EditionValueLabel.Text = ('{0} | Version {1}' -f $info.EditionId, $info.DisplayVersion) if ($null -ne $license) { $licenseStatus = Get-LicenseStatusName $license.LicenseStatus $reason = Format-HResult $license.LicenseStatusReason $partial = if ([string]::IsNullOrWhiteSpace($license.PartialProductKey)) { 'none' } else { $license.PartialProductKey } $script:ActivationValueLabel.Text = ('{0} | Key last 5: {1} | Reason: {2}' -f $licenseStatus, $partial, $reason) } else { $script:ActivationValueLabel.Text = 'No Windows licensing product was found.' } $script:HomeProButton.Enabled = $script:IsHomeEdition $script:StatusLabel.Text = if ($script:IsHomeEdition) { 'Home/Core detected. For a Pro FPP key, use "Home to Pro via Windows Activation".' } else { 'Ready.' } $script:LastDiagnostics = Get-DiagnosticsText } catch { $script:StatusLabel.Text = 'Could not refresh Windows licensing info.'; Append-Log ('Refresh failed: {0}' -f $_.Exception.Message) } } function Show-ConnectivityChecks { Set-Busy $true try { Append-Log 'Running Microsoft activation connectivity checks...' $check = Invoke-ConnectivityChecks foreach ($line in ($check.Text -split "`r`n")) { if (-not [string]::IsNullOrWhiteSpace($line)) { Append-Log $line } } $script:StatusLabel.Text = if ($check.HasBlockingFailures) { 'Connectivity check found blocking issues.' } else { 'Connectivity check completed.' } $icon = if ($check.HasBlockingFailures) { [System.Windows.Forms.MessageBoxIcon]::Warning } else { [System.Windows.Forms.MessageBoxIcon]::Information } [System.Windows.Forms.MessageBox]::Show($check.Text, 'Microsoft activation connectivity check', [System.Windows.Forms.MessageBoxButtons]::OK, $icon) | Out-Null } finally { Set-Busy $false } } function Start-CurrentEditionActivation { $validation = Get-ProductKeyValidation $script:KeyTextBox.Text $script:KeyTextBox.Text = $validation.Key if (-not $validation.Valid) { [System.Windows.Forms.MessageBox]::Show('Enter a 25-character Windows product key in XXXXX-XXXXX-XXXXX-XXXXX-XXXXX format.', 'Invalid key format', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning) | Out-Null; return } if ($script:IsHomeEdition) { $choice = [System.Windows.Forms.MessageBox]::Show('This PC is running Home/Core. Use this automatic path only for a Home key. If this is a Pro key, choose the Home to Pro button so Windows handles the edition upgrade through Activation Settings.', 'Confirm current-edition activation', [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning) if ($choice -ne [System.Windows.Forms.DialogResult]::Yes) { return } } Set-Busy $true $attemptResponses = New-Object System.Collections.Generic.List[object] $install = $null $activation = $null $retryActivation = $null $slmgr = $null try { $last5 = $validation.Last5; $productKey = $validation.Key; $validation = $null; Clear-ProductKeyInput if ($script:PreflightCheckBox.Checked) { Append-Log 'Running preflight checks before activation...' $preflight = Invoke-ConnectivityChecks foreach ($line in ($preflight.Text -split "`r`n")) { if (-not [string]::IsNullOrWhiteSpace($line)) { Append-Log $line } } if ($preflight.HasBlockingFailures) { $choice = [System.Windows.Forms.MessageBox]::Show(('The connectivity preflight found blocking issues:{0}{0}{1}{0}{0}Continue activation anyway?' -f [Environment]::NewLine, $preflight.Text), 'Connectivity warning', [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning) if ($choice -ne [System.Windows.Forms.DialogResult]::Yes) { $script:StatusLabel.Text = 'Activation canceled because connectivity checks failed.'; return } } } else { $serviceCheck = Ensure-SoftwareProtectionService if ($serviceCheck.Success) { Append-Log ('Quick service check: {0}' -f $serviceCheck.Message) } else { Append-Log ('Software Protection Service warning: {0}' -f $serviceCheck.Message) } } Append-Log ('Installing product key ending in {0} through Windows Software Licensing Provider...' -f $last5) $install = Invoke-InstallProductKey -ProductKey $productKey $attemptResponses.Add($install) | Out-Null $productKey = $null; [System.GC]::Collect() Append-Log (Format-ActivationResponseForLog $install) if (-not $install.Success) { $snapshot = Get-LicenseSnapshot -PartialKey $last5 $report = Format-ActivationAttemptReport -Responses $attemptResponses.ToArray() -Snapshot $snapshot $manualResponse = Get-ManualResolvableResponse -Responses $attemptResponses.ToArray() -Snapshot $snapshot if ($null -ne $manualResponse) { $manualReport = Invoke-ManualActivationResolution -Response $manualResponse -PartialKey $last5 $report = ('{0}{1}{1}{2}' -f $report, [Environment]::NewLine, $manualReport) } Update-SystemInfo $script:StatusLabel.Text = ('Install failed: {0} - {1}' -f $install.Code, $install.Title) Show-ActivationReport -Title 'Product key install failed' -Report $report -Icon ([System.Windows.Forms.MessageBoxIcon]::Warning) return } Invoke-RefreshLicenseStatus $null = Wait-LicenseProductByPartialKey -PartialKey $last5 -TimeoutMs 1800 Append-Log 'Requesting online activation from Windows licensing service...' $activation = Invoke-ActivateWindows -PartialKey $last5 $attemptResponses.Add($activation) | Out-Null Append-Log (Format-ActivationResponseForLog $activation) if (-not $activation.Success -and $activation.Retry) { Append-Log 'Activation error looks retryable. Running safe automatic remediation before retry...' $null = Invoke-ActivationRemediation -Response $activation -PartialKey $last5 Append-Log 'Retrying WMI activation after remediation...' $retryActivation = Invoke-ActivateWindows -PartialKey $last5 $attemptResponses.Add($retryActivation) | Out-Null Append-Log ('Retry result: {0}' -f (Format-ActivationResponseForLog $retryActivation)) $activation = $retryActivation } Update-SystemInfo if ($activation.Success) { $snapshot = Get-LicenseSnapshot -PartialKey $last5 $report = Format-ActivationAttemptReport -Responses $attemptResponses.ToArray() -Snapshot $snapshot $script:LastActivationSummary = $report $script:StatusLabel.Text = 'Activation request completed. Check the activation state above.' [System.Windows.Forms.MessageBox]::Show('Activation request completed. The current activation state is shown in the main window.', 'Activation finished', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null } else { if ($activation.HardStop) { Append-Log ('Hard stop: {0}. slmgr fallback cannot make this key/license valid.' -f $activation.Title) } elseif ($script:FallbackCheckBox.Checked) { Append-Log 'WMI activation did not complete. Trying official slmgr.vbs /ato fallback...' $slmgr = Invoke-SlmgrActivate -PartialKey $last5 $attemptResponses.Add($slmgr) | Out-Null Append-Log (Format-ActivationResponseForLog $slmgr) Append-Log ('slmgr /ato license status: {0}' -f $slmgr.LicenseStatus) if (-not [string]::IsNullOrWhiteSpace($slmgr.LicenseReason) -and $slmgr.LicenseReason -ne $slmgr.Code) { Append-Log ('slmgr license reason: {0} - {1}' -f $slmgr.LicenseReason, $slmgr.LicenseHint) } Update-SystemInfo if ($slmgr.Success) { $snapshot = Get-LicenseSnapshot -PartialKey $last5 $report = Format-ActivationAttemptReport -Responses $attemptResponses.ToArray() -Snapshot $snapshot $script:LastActivationSummary = $report $script:StatusLabel.Text = 'Activation completed through slmgr fallback. Check the activation state above.' [System.Windows.Forms.MessageBox]::Show('Activation completed through the official slmgr.vbs fallback. The current activation state is shown in the main window.', 'Activation finished', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null return } } else { Append-Log 'slmgr fallback skipped because "slmgr fallback" is not enabled.'; Update-SystemInfo } $snapshot = Get-LicenseSnapshot -PartialKey $last5 if (-not [string]::IsNullOrWhiteSpace($snapshot.Reason) -and $snapshot.Reason -ne $activation.Code) { Append-Log ('Windows license reason after failure: {0} - {1}' -f $snapshot.Reason, $snapshot.Hint) } $report = Format-ActivationAttemptReport -Responses $attemptResponses.ToArray() -Snapshot $snapshot $manualResponse = Get-ManualResolvableResponse -Responses $attemptResponses.ToArray() -Snapshot $snapshot if ($null -ne $manualResponse) { $manualReport = Invoke-ManualActivationResolution -Response $manualResponse -PartialKey $last5 $report = ('{0}{1}{1}{2}' -f $report, [Environment]::NewLine, $manualReport) } $script:StatusLabel.Text = if ([string]::IsNullOrWhiteSpace($snapshot.Reason)) { ('Activation failed: {0} - {1}' -f $activation.Code, $activation.Title) } else { ('Activation failed: {0}; reason: {1}' -f $activation.Code, $snapshot.Reason) } Show-ActivationReport -Title 'Activation error' -Report $report -Icon ([System.Windows.Forms.MessageBoxIcon]::Warning) } } finally { $productKey = $null; Clear-ProductKeyInput; Set-Busy $false; $script:KeyTextBox.Focus() } } function Start-HomeToProFlow { $validation = Get-ProductKeyValidation $script:KeyTextBox.Text $hasInput = -not [string]::IsNullOrWhiteSpace($script:KeyTextBox.Text) if ($hasInput -and -not $validation.Valid) { [System.Windows.Forms.MessageBox]::Show('The entered key does not match XXXXX-XXXXX-XXXXX-XXXXX-XXXXX format. For privacy, you can also leave this box blank and enter the Pro key directly in Windows Activation Settings.', 'Invalid key format', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning) | Out-Null; return } if ($hasInput) { Append-Log ('Opening Windows Activation Settings for product key ending in {0}. Full key was not copied or stored.' -f $validation.Last5) } else { Append-Log 'Opening Windows Activation Settings. No product key was entered into the tool.' } Clear-ProductKeyInput; Start-Process 'ms-settings:activation' $script:StatusLabel.Text = 'Activation Settings opened. Choose Change product key, enter the Pro key, then follow Windows prompts.' [System.Windows.Forms.MessageBox]::Show('Windows Activation Settings was opened. For privacy, this tool did not copy or store the full key and the input box was cleared. Choose "Change product key", enter the Pro key, then let Windows perform the Home to Pro upgrade. A restart may be required.', 'Home to Pro via Microsoft Activation', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null } function Open-ActivationSettings { Start-Process 'ms-settings:activation' } function Copy-Diagnostics { try { $text = Get-DiagnosticsText; Set-ClipboardText $text; Append-Log 'Diagnostics copied to clipboard.'; $script:StatusLabel.Text = 'Diagnostics copied to clipboard.' } catch { Append-Log ('Copy diagnostics failed: {0}' -f $_.Exception.Message) } } function Open-ProductActivationPortal { try { Start-Process 'https://visualsupport.microsoft.com/' Append-Log 'Opened Microsoft Product Activation portal.' } catch { Append-Log ('Could not open Microsoft activation portal: {0}' -f $_.Exception.Message) } } function Get-ActivationIdForSlmgr { param([string]$PartialKey) try { $product = Get-WindowsLicenseProduct -PartialKey $PartialKey if ($null -ne $product -and $product.PSObject.Properties.Name -contains 'ID') { return [string]$product.ID } } catch { } return '' } function Format-DigitGroups { param([string]$Digits, [int]$GroupSize) if ([string]::IsNullOrWhiteSpace($Digits)) { return '' } $parts = New-Object System.Collections.Generic.List[string] for ($i = 0; $i -lt $Digits.Length; $i += $GroupSize) { $parts.Add($Digits.Substring($i, [Math]::Min($GroupSize, $Digits.Length - $i))) } return ($parts -join ' ') } function Invoke-SlmgrDisplayInstallationId { param([string]$PartialKey) $scriptPath = Join-Path $env:windir 'System32\slmgr.vbs' $cscriptPath = Join-Path $env:windir 'System32\cscript.exe' $activationId = Get-ActivationIdForSlmgr -PartialKey $PartialKey $arguments = if ([string]::IsNullOrWhiteSpace($activationId)) { ('//nologo "{0}" /dti' -f $scriptPath) } else { ('//nologo "{0}" /dti {1}' -f $scriptPath, $activationId) } $result = Invoke-ProcessCapture -FileName $cscriptPath -Arguments $arguments -TimeoutSeconds 30 $text = (($result.Output + "`r`n" + $result.Error).Trim()) $digits = ($text -replace '[^\d]', '') if ($digits.Length -gt 63) { $digits = $digits.Substring($digits.Length - 63, 63) } $success = (-not $result.TimedOut -and $digits.Length -ge 54) return [pscustomobject]@{ Success = $success ActivationId = $activationId InstallationId = $digits InstallationGroups = (Format-DigitGroups -Digits $digits -GroupSize 7) Output = $text ExitCode = $result.ExitCode TimedOut = $result.TimedOut } } function Normalize-ConfirmationId { param([string]$Text) if ([string]::IsNullOrWhiteSpace($Text)) { return '' } return ($Text -replace '[^\d]', '') } function Show-ConfirmationIdPrompt { param([string]$InstallationGroups) $form = New-Object System.Windows.Forms.Form $form.Text = 'Phone Activation Assistant' $form.StartPosition = 'CenterParent' $form.Size = New-Object System.Drawing.Size -ArgumentList 720, 520 $form.Font = New-Object System.Drawing.Font -ArgumentList 'Segoe UI', 9 $label = New-Object System.Windows.Forms.Label $label.Text = ('Manual steps left:{0}1. Complete Microsoft puzzle/CAPTCHA yourself.{0}2. Sign in with the customer Microsoft account if Microsoft asks.{0}3. Paste/provide the Installation ID below, then copy the Confirmation ID back here.{0}{0}Installation ID:{0}{1}' -f [Environment]::NewLine, $InstallationGroups) $label.Location = New-Object System.Drawing.Point -ArgumentList 16, 14 $label.Size = New-Object System.Drawing.Size -ArgumentList 670, 128 $form.Controls.Add($label) $copyIid = New-Object System.Windows.Forms.Button $copyIid.Text = 'Copy Installation ID' $copyIid.Location = New-Object System.Drawing.Point -ArgumentList 16, 150 $copyIid.Size = New-Object System.Drawing.Size -ArgumentList 132, 30 $copyIid.Add_Click({ Set-ClipboardText $InstallationGroups }) $form.Controls.Add($copyIid) $typeIid = New-Object System.Windows.Forms.Button $typeIid.Text = 'Type IID' $typeIid.Location = New-Object System.Drawing.Point -ArgumentList 158, 150 $typeIid.Size = New-Object System.Drawing.Size -ArgumentList 82, 30 $form.Controls.Add($typeIid) $portalButton = New-Object System.Windows.Forms.Button $portalButton.Text = 'Open Portal' $portalButton.Location = New-Object System.Drawing.Point -ArgumentList 250, 150 $portalButton.Size = New-Object System.Drawing.Size -ArgumentList 102, 30 $portalButton.Add_Click({ Open-ProductActivationPortal }) $form.Controls.Add($portalButton) $sluiButton = New-Object System.Windows.Forms.Button $sluiButton.Text = 'Open SLUI 04' $sluiButton.Location = New-Object System.Drawing.Point -ArgumentList 362, 150 $sluiButton.Size = New-Object System.Drawing.Size -ArgumentList 104, 30 $sluiButton.Add_Click({ try { Start-Process -FilePath (Join-Path $env:windir 'System32\slui.exe') -ArgumentList '4' } catch { } }) $form.Controls.Add($sluiButton) $pasteButton = New-Object System.Windows.Forms.Button $pasteButton.Text = 'Paste CID' $pasteButton.Location = New-Object System.Drawing.Point -ArgumentList 476, 150 $pasteButton.Size = New-Object System.Drawing.Size -ArgumentList 92, 30 $form.Controls.Add($pasteButton) $watchCheck = New-Object System.Windows.Forms.CheckBox $watchCheck.Text = 'Auto-detect Confirmation ID from clipboard' $watchCheck.Location = New-Object System.Drawing.Point -ArgumentList 16, 188 $watchCheck.Size = New-Object System.Drawing.Size -ArgumentList 220, 24 $watchCheck.Checked = $true $form.Controls.Add($watchCheck) $autoApplyCheck = New-Object System.Windows.Forms.CheckBox $autoApplyCheck.Text = 'Auto-apply CID when detected' $autoApplyCheck.Location = New-Object System.Drawing.Point -ArgumentList 270, 188 $autoApplyCheck.Size = New-Object System.Drawing.Size -ArgumentList 190, 24 $autoApplyCheck.Checked = $true $form.Controls.Add($autoApplyCheck) $box = New-Object System.Windows.Forms.TextBox $box.Location = New-Object System.Drawing.Point -ArgumentList 16, 224 $box.Size = New-Object System.Drawing.Size -ArgumentList 670, 120 $box.Multiline = $true $box.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical $box.Font = New-Object System.Drawing.Font -ArgumentList 'Consolas', 11 $form.Controls.Add($box) $status = New-Object System.Windows.Forms.Label $status.Text = 'Waiting for 48-digit Confirmation ID from Microsoft.' $status.Location = New-Object System.Drawing.Point -ArgumentList 16, 352 $status.Size = New-Object System.Drawing.Size -ArgumentList 670, 24 $form.Controls.Add($status) $ok = New-Object System.Windows.Forms.Button $ok.Text = 'Apply CID' $ok.Location = New-Object System.Drawing.Point -ArgumentList 506, 414 $ok.Size = New-Object System.Drawing.Size -ArgumentList 84, 30 $ok.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $ok $form.Controls.Add($ok) $cancel = New-Object System.Windows.Forms.Button $cancel.Text = 'Cancel' $cancel.Location = New-Object System.Drawing.Point -ArgumentList 602, 414 $cancel.Size = New-Object System.Drawing.Size -ArgumentList 84, 30 $cancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $cancel $form.Controls.Add($cancel) $updateStatus = { $digits = Normalize-ConfirmationId $box.Text if ($digits.Length -eq 48) { $status.Text = 'Ready: 48 digits detected. Click Apply CID.' $status.ForeColor = [System.Drawing.Color]::DarkGreen } elseif ($digits.Length -gt 0) { $status.Text = ('Need 48 digits. Current digits: {0}.' -f $digits.Length) $status.ForeColor = [System.Drawing.Color]::DarkOrange } else { $status.Text = 'Waiting for 48-digit Confirmation ID from Microsoft.' $status.ForeColor = [System.Drawing.Color]::Black } } $box.Add_TextChanged($updateStatus) $typeIid.Add_Click({ $parts = @($InstallationGroups -split '\s+' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) if ($parts.Count -eq 0) { return } Set-ClipboardText $InstallationGroups [System.Windows.Forms.MessageBox]::Show('After clicking OK, focus the first Installation ID field in the Microsoft portal. The tool will type all 9 groups after 5 seconds.', 'Auto type Installation ID', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null for ($i = 5; $i -ge 1; $i--) { $status.Text = ('Focus the first Installation ID field now. Typing in {0}...' -f $i) $status.ForeColor = [System.Drawing.Color]::DarkBlue [System.Windows.Forms.Application]::DoEvents() Start-Sleep -Seconds 1 } try { $sequence = ($parts -join '{TAB}') [System.Windows.Forms.SendKeys]::SendWait($sequence) $status.Text = 'Installation ID typed into the active window.' $status.ForeColor = [System.Drawing.Color]::DarkGreen } catch { $status.Text = ('Could not type Installation ID: {0}' -f $_.Exception.Message) $status.ForeColor = [System.Drawing.Color]::DarkRed } }) $pasteButton.Add_Click({ try { if ([System.Windows.Forms.Clipboard]::ContainsText()) { $box.Text = [System.Windows.Forms.Clipboard]::GetText() } } catch { } }) $timer = New-Object System.Windows.Forms.Timer $timer.Interval = 1500 $timer.Add_Tick({ if (-not $watchCheck.Checked) { return } try { if (-not [System.Windows.Forms.Clipboard]::ContainsText()) { return } $clip = [System.Windows.Forms.Clipboard]::GetText() $digits = Normalize-ConfirmationId $clip if ($digits.Length -eq 48 -and (Normalize-ConfirmationId $box.Text) -ne $digits) { $box.Text = $clip $status.Text = 'Confirmation ID detected from clipboard.' $status.ForeColor = [System.Drawing.Color]::DarkGreen if ($autoApplyCheck.Checked) { $timer.Stop() $form.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.Close() } } } catch { } }) $form.Add_Shown({ $timer.Start(); & $updateStatus }) $form.Add_FormClosed({ $timer.Stop(); $timer.Dispose() }) $dialog = $form.ShowDialog($script:Form) if ($dialog -ne [System.Windows.Forms.DialogResult]::OK) { return '' } return $box.Text } function Invoke-SlmgrApplyConfirmationId { param([string]$ConfirmationId, [string]$ActivationId) $digits = Normalize-ConfirmationId $ConfirmationId if ($digits.Length -ne 48) { return [pscustomobject]@{ Success = $false; Code = 'InvalidCID'; Message = ('Confirmation ID must contain 48 digits. Current digits: {0}.' -f $digits.Length); Output = ''; Digits = $digits } } $scriptPath = Join-Path $env:windir 'System32\slmgr.vbs' $cscriptPath = Join-Path $env:windir 'System32\cscript.exe' $arguments = if ([string]::IsNullOrWhiteSpace($ActivationId)) { ('//nologo "{0}" /atp {1}' -f $scriptPath, $digits) } else { ('//nologo "{0}" /atp {1} {2}' -f $scriptPath, $digits, $ActivationId) } $result = Invoke-ProcessCapture -FileName $cscriptPath -Arguments $arguments -TimeoutSeconds 60 Invoke-RefreshLicenseStatus $snapshot = Get-LicenseSnapshot -PartialKey '' $text = (($result.Output + "`r`n" + $result.Error).Trim()) $code = if ($text -match '0x([0-9A-Fa-f]{8})') { ('0x{0}' -f $matches[1].ToUpperInvariant()) } else { ('ExitCode {0}' -f $result.ExitCode) } $success = ($snapshot.Status -eq 'Licensed' -or $code -eq '0x00000000' -or ($result.ExitCode -eq 0 -and $text -notmatch '0x[0-9A-Fa-f]{8}')) if ($success -and $code -like 'ExitCode *') { $code = '0x00000000' } return [pscustomobject]@{ Success = $success; Code = $code; Message = $text; Output = $text; Digits = $digits; LicenseStatus = $snapshot.Status; LicenseReason = $snapshot.Reason; LicenseHint = $snapshot.Hint } } function Start-PhoneActivationAssistant { param([string]$PartialKey = '') Set-Busy $true try { Append-Log 'Starting phone/manual activation assistant for 0xC004C008...' $dti = Invoke-SlmgrDisplayInstallationId -PartialKey $PartialKey if (-not $dti.Success) { Append-Log ('Could not collect Installation ID automatically. slmgr output: {0}' -f $dti.Output) } else { Set-ClipboardText $dti.InstallationGroups Append-Log ('Installation ID copied: {0}' -f $dti.InstallationGroups) } try { Start-Process 'ms-settings:activation'; Append-Log 'Opened Windows Activation Settings.' } catch { Append-Log ('Could not open Activation Settings: {0}' -f $_.Exception.Message) } try { Start-Process -FilePath (Join-Path $env:windir 'System32\slui.exe') -ArgumentList '4'; Append-Log 'Opened SLUI 04 phone activation.' } catch { Append-Log ('Could not open SLUI 04: {0}' -f $_.Exception.Message) } Open-ProductActivationPortal $cidText = Show-ConfirmationIdPrompt -InstallationGroups $dti.InstallationGroups if ([string]::IsNullOrWhiteSpace($cidText)) { $script:StatusLabel.Text = 'Phone activation assistant opened. Paste Confirmation ID later to apply it.' return } $apply = Invoke-SlmgrApplyConfirmationId -ConfirmationId $cidText -ActivationId $dti.ActivationId Append-Log ('Confirmation ID apply result: {0} - {1}' -f $apply.Code, $apply.Message) Update-SystemInfo if ($apply.Success) { $script:StatusLabel.Text = 'Phone activation completed. Windows should now show Licensed.' [System.Windows.Forms.MessageBox]::Show('Confirmation ID was applied and Windows reports Licensed.', 'Phone activation completed', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null } else { $script:StatusLabel.Text = ('Confirmation ID apply failed: {0}' -f $apply.Code) [System.Windows.Forms.MessageBox]::Show(('Could not apply Confirmation ID:{0}{0}{1}{0}{0}License status: {2}{0}Reason: {3}' -f [Environment]::NewLine, $apply.Message, $apply.LicenseStatus, $apply.LicenseReason), 'Phone activation error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning) | Out-Null } } finally { Set-Busy $false } } function Get-ManualActivationChecklist { param([object]$Response, [object]$Snapshot) $steps = @() if ($null -ne $Response -and $null -ne $Response.ManualSteps) { $steps = @($Response.ManualSteps | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) }) } if ($steps.Count -eq 0) { $steps = @( 'Open Activation Settings.', 'Choose the phone/manual activation path if Windows offers it.', 'Provide the Installation ID to Microsoft.', 'Enter the Confirmation ID returned by Microsoft.', 'Refresh activation status.' ) } $lines = New-Object System.Collections.Generic.List[string] $lines.Add('Manual resolution for 0xC004C008') | Out-Null $lines.Add('') | Out-Null $lines.Add('What the tool can do: open the official Windows manual activation entry points and preserve diagnostics.') | Out-Null $lines.Add('What must stay manual: Microsoft must issue a valid Confirmation ID after checking the license/installation ID.') | Out-Null $lines.Add('') | Out-Null for ($i = 0; $i -lt $steps.Count; $i++) { $lines.Add(('{0}. {1}' -f ($i + 1), $steps[$i])) | Out-Null } if ($null -ne $Snapshot) { $lines.Add('') | Out-Null $lines.Add(('Current license status: {0}' -f $Snapshot.Status)) | Out-Null if (-not [string]::IsNullOrWhiteSpace($Snapshot.Reason)) { $lines.Add(('Current license reason: {0}' -f $Snapshot.Reason)) | Out-Null } } $lines.Add('') | Out-Null $lines.Add('If Microsoft refuses the Confirmation ID, this key cannot be activated on this PC; use another valid key or contact the seller/licensing owner.') | Out-Null return ($lines.ToArray() -join "`r`n") } function Invoke-ManualActivationResolution { param([object]$Response, [string]$PartialKey) $snapshot = Get-LicenseSnapshot -PartialKey $PartialKey $checklist = Get-ManualActivationChecklist -Response $Response -Snapshot $snapshot Append-Log 'Manual activation path required for 0xC004C008.' try { Set-ClipboardText $checklist Append-Log 'Manual activation checklist copied to clipboard.' } catch { Append-Log ('Could not copy manual checklist: {0}' -f $_.Exception.Message) } Start-PhoneActivationAssistant -PartialKey $PartialKey return $checklist } function Get-ManualResolvableResponse { param([object[]]$Responses, [object]$Snapshot) $manual = @($Responses | Where-Object { $null -ne $_ -and $_.ManualResolve } | Select-Object -Last 1) if ($manual.Count -gt 0) { return $manual[0] } if ($null -ne $Snapshot -and (Normalize-ActivationCode $Snapshot.Reason) -eq '0xC004C008') { return (New-ActivationResponse -Phase 'License snapshot reason' -Success $false -Code '0xC004C008' -Message (Get-ErrorHint '0xC004C008')) } return $null } function Invoke-ActivationRemediation { param([object]$Response, [string]$PartialKey) $fixes = @() if ($null -ne $Response -and $null -ne $Response.AutoFix) { $fixes = @($Response.AutoFix | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) } | Select-Object -Unique) } if ($fixes.Count -eq 0) { Append-Log 'No safe automatic remediation is available for this activation result.' return [pscustomobject]@{ Ran = $false; Message = 'No automatic remediation available.' } } Append-Log ('Automatic remediation for {0}: {1}' -f $Response.Code, ($fixes -join ', ')) foreach ($fix in $fixes) { switch ($fix) { 'Wait' { Append-Log 'Waiting for Windows activation/update operations to settle...' Start-Sleep -Seconds 5 } 'ServiceRefresh' { $svc = Ensure-SoftwareProtectionService Append-Log ('sppsvc remediation: {0}' -f $svc.Message) } 'LicenseRefresh' { Invoke-RefreshLicenseStatus $snapshot = Get-LicenseSnapshot -PartialKey $PartialKey Append-Log ('License refresh: status={0}; reason={1}' -f $snapshot.Status, $snapshot.Reason) } 'TimeSync' { try { $timeSvc = Get-Service -Name w32time -ErrorAction Stop if ($timeSvc.Status -ne 'Running') { Start-Service -Name w32time -ErrorAction SilentlyContinue } } catch { Append-Log ('Windows Time service check failed: {0}' -f $_.Exception.Message) } $w32 = Invoke-ProcessCapture -FileName (Join-Path $env:windir 'System32\w32tm.exe') -Arguments '/resync /nowait' -TimeoutSeconds 8 $detail = Get-FirstUsefulLine (($w32.Output + "`r`n" + $w32.Error).Trim()) if ([string]::IsNullOrWhiteSpace($detail)) { $detail = ('exit={0}; timedOut={1}' -f $w32.ExitCode, $w32.TimedOut) } Append-Log ('Time sync remediation: {0}' -f $detail) } 'DnsFlush' { $dns = Invoke-ProcessCapture -FileName (Join-Path $env:windir 'System32\ipconfig.exe') -Arguments '/flushdns' -TimeoutSeconds 8 $detail = Get-FirstUsefulLine (($dns.Output + "`r`n" + $dns.Error).Trim()) if ([string]::IsNullOrWhiteSpace($detail)) { $detail = ('exit={0}; timedOut={1}' -f $dns.ExitCode, $dns.TimedOut) } Append-Log ('DNS flush remediation: {0}' -f $detail) } 'ConnectivityCheck' { $check = Invoke-ConnectivityChecks $connDetail = if ($check.HasBlockingFailures) { 'blocking issues remain' } else { 'no blocking issues detected' } Append-Log ('Connectivity remediation: {0}' -f $connDetail) } default { Append-Log ('Unknown remediation step skipped: {0}' -f $fix) } } } return [pscustomobject]@{ Ran = $true; Message = ($fixes -join ', ') } } function Format-ActivationAttemptReport { param([object[]]$Responses, [object]$Snapshot) $lines = New-Object System.Collections.Generic.List[string] $lines.Add('Activation attempt report') | Out-Null foreach ($response in $Responses) { if ($null -eq $response) { continue } $code = if ([string]::IsNullOrWhiteSpace($response.Code)) { 'no-code' } else { [string]$response.Code } $lines.Add(('Phase: {0}' -f $response.Phase)) | Out-Null $lines.Add(('Code: {0}' -f $code)) | Out-Null $lines.Add(('Result: {0}' -f $response.Title)) | Out-Null if (-not [string]::IsNullOrWhiteSpace($response.Message)) { $lines.Add(('Windows message: {0}' -f (($response.Message -replace "(`r`n|`n|`r)", ' ').Trim()))) | Out-Null } if (-not [string]::IsNullOrWhiteSpace($response.Meaning)) { $lines.Add(('Meaning: {0}' -f $response.Meaning)) | Out-Null } if (-not [string]::IsNullOrWhiteSpace($response.Guidance)) { $lines.Add(('Next step: {0}' -f $response.Guidance)) | Out-Null } $fixText = if ($response.ManualResolve) { ('Manual resolution: {0}' -f $response.ManualAction) } elseif ($response.HardStop) { 'Hard stop; requires a valid matching license/key or Microsoft/IT action.' } elseif ($null -ne $response.AutoFix -and @($response.AutoFix).Count -gt 0) { ('Auto-fix attempted/available: {0}' -f (@($response.AutoFix) -join ', ')) } else { 'No automatic fix for this result.' } $lines.Add(('Tool action: {0}' -f $fixText)) | Out-Null $lines.Add('') | Out-Null } if ($null -ne $Snapshot) { $lines.Add(('Current license status: {0}' -f $Snapshot.Status)) | Out-Null if (-not [string]::IsNullOrWhiteSpace($Snapshot.Reason)) { $lines.Add(('Current license reason: {0}' -f $Snapshot.Reason)) | Out-Null } if (-not [string]::IsNullOrWhiteSpace($Snapshot.Hint)) { $lines.Add(('Current license hint: {0}' -f $Snapshot.Hint)) | Out-Null } } return ($lines.ToArray() -join "`r`n").Trim() } function Show-ActivationReport { param([string]$Title, [string]$Report, [System.Windows.Forms.MessageBoxIcon]$Icon) if ([string]::IsNullOrWhiteSpace($Report)) { return } $script:LastActivationSummary = $Report [System.Windows.Forms.MessageBox]::Show($Report, $Title, [System.Windows.Forms.MessageBoxButtons]::OK, $Icon) | Out-Null } # ============================================================ # SAFE SIMULATION BUTTON (no product-key or activation side effects) # ============================================================ function Run-QuickBench { Set-Busy $true try { Append-Log '--- Activation error simulation starting ---' $script:BenchResults.Clear() $rows = New-Object System.Collections.Generic.List[object] foreach ($issue in ($script:ActivationIssueCatalog.Values | Sort-Object Code)) { $response = New-ActivationResponse -Phase 'Simulation' -Success ($issue.Code -eq '0x00000000') -Code $issue.Code -Message '' $rows.Add([pscustomobject]@{ Code = $response.Code Title = $response.Title Category = $response.Category Retry = $response.Retry OpenSettings = $response.OpenSettings Phone = $response.Phone Meaning = $response.Meaning NextStep = $response.Guidance }) | Out-Null } $benchPath = Join-Path $env:USERPROFILE 'wkt-activation-error-simulation.csv' $rows | Export-Csv -Path $benchPath -NoTypeInformation -Encoding UTF8 Append-Log ('Simulated {0} activation result codes.' -f $rows.Count) Append-Log ('Simulation CSV: {0}' -f $benchPath) $lines = @( ('Simulated {0} activation result codes.' -f $rows.Count), '', ('CSV: {0}' -f $benchPath), '', 'This simulation does not install keys or call Windows activation.' ) [System.Windows.Forms.MessageBox]::Show(($lines -join "`r`n"), 'Activation error simulation', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null } catch { Append-Log ('Simulation failed: {0}' -f $_.Exception.Message) } finally { Set-Busy $false } } # ============================================================ # GUI # ============================================================ $script:IsHomeEdition = $false $script:Form = New-Object System.Windows.Forms.Form $script:Form.Text = 'Windows Key Tool (Optimized)' $script:Form.StartPosition = 'CenterScreen' $script:Form.Size = New-Object System.Drawing.Size -ArgumentList 820, 690 $script:Form.MinimumSize = New-Object System.Drawing.Size -ArgumentList 760, 640 $script:Form.Font = New-Object System.Drawing.Font -ArgumentList 'Segoe UI', 9 $titleLabel = New-Object System.Windows.Forms.Label $titleLabel.Text = 'Windows Key Tool (Optimized)' $titleLabel.Font = New-Object System.Drawing.Font -ArgumentList 'Segoe UI Semibold', 18 $titleLabel.AutoSize = $true; $titleLabel.Location = New-Object System.Drawing.Point -ArgumentList 22, 18 $script:Form.Controls.Add($titleLabel) $subtitleLabel = New-Object System.Windows.Forms.Label $subtitleLabel.Text = 'Official activation paths only. Handles known activation errors with guided recovery.' $subtitleLabel.AutoSize = $true; $subtitleLabel.Location = New-Object System.Drawing.Point -ArgumentList 26, 55 $script:Form.Controls.Add($subtitleLabel) $y = 92 $windowsLabel = New-Object System.Windows.Forms.Label; $windowsLabel.Text = 'Windows'; $windowsLabel.AutoSize = $true; $windowsLabel.Location = New-Object System.Drawing.Point -ArgumentList 28, $y; $script:Form.Controls.Add($windowsLabel) $script:WindowsValueLabel = New-Object System.Windows.Forms.Label; $script:WindowsValueLabel.Text = 'Loading...'; $script:WindowsValueLabel.AutoSize = $false; $script:WindowsValueLabel.Size = New-Object System.Drawing.Size -ArgumentList 720, 22; $script:WindowsValueLabel.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:Form.Controls.Add($script:WindowsValueLabel) $y += 30 $editionLabel = New-Object System.Windows.Forms.Label; $editionLabel.Text = 'Edition'; $editionLabel.AutoSize = $true; $editionLabel.Location = New-Object System.Drawing.Point -ArgumentList 28, $y; $script:Form.Controls.Add($editionLabel) $script:EditionValueLabel = New-Object System.Windows.Forms.Label; $script:EditionValueLabel.Text = 'Loading...'; $script:EditionValueLabel.AutoSize = $false; $script:EditionValueLabel.Size = New-Object System.Drawing.Size -ArgumentList 720, 22; $script:EditionValueLabel.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:Form.Controls.Add($script:EditionValueLabel) $y += 30 $activationLabel = New-Object System.Windows.Forms.Label; $activationLabel.Text = 'Activation'; $activationLabel.AutoSize = $true; $activationLabel.Location = New-Object System.Drawing.Point -ArgumentList 28, $y; $script:Form.Controls.Add($activationLabel) $script:ActivationValueLabel = New-Object System.Windows.Forms.Label; $script:ActivationValueLabel.Text = 'Loading...'; $script:ActivationValueLabel.AutoSize = $false; $script:ActivationValueLabel.Size = New-Object System.Drawing.Size -ArgumentList 720, 22; $script:ActivationValueLabel.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:Form.Controls.Add($script:ActivationValueLabel) $y += 48 $keyLabel = New-Object System.Windows.Forms.Label; $keyLabel.Text = 'Product key'; $keyLabel.AutoSize = $true; $keyLabel.Location = New-Object System.Drawing.Point -ArgumentList 28, ($y + 5); $script:Form.Controls.Add($keyLabel) $script:KeyTextBox = New-Object System.Windows.Forms.TextBox $script:KeyTextBox.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:KeyTextBox.Size = New-Object System.Drawing.Size -ArgumentList 360, 24; $script:KeyTextBox.CharacterCasing = [System.Windows.Forms.CharacterCasing]::Upper; $script:KeyTextBox.Font = New-Object System.Drawing.Font -ArgumentList 'Consolas', 10 $script:KeyTextBox.Add_Leave({ $script:KeyTextBox.Text = Format-ProductKey $script:KeyTextBox.Text }) $script:Form.Controls.Add($script:KeyTextBox) $pasteButton = New-Object System.Windows.Forms.Button; $pasteButton.Text = 'Paste'; $pasteButton.Location = New-Object System.Drawing.Point -ArgumentList 532, ($y - 1); $pasteButton.Size = New-Object System.Drawing.Size -ArgumentList 80, 28 $pasteButton.Add_Click({ if ([System.Windows.Forms.Clipboard]::ContainsText()) { $script:KeyTextBox.Text = Format-ProductKey ([System.Windows.Forms.Clipboard]::GetText()) } }) $script:Form.Controls.Add($pasteButton) $clearButton = New-Object System.Windows.Forms.Button; $clearButton.Text = 'Clear'; $clearButton.Location = New-Object System.Drawing.Point -ArgumentList 620, ($y - 1); $clearButton.Size = New-Object System.Drawing.Size -ArgumentList 80, 28 $clearButton.Add_Click({ $script:KeyTextBox.Clear() }) $script:Form.Controls.Add($clearButton) $y += 50 $script:ActivateButton = New-Object System.Windows.Forms.Button; $script:ActivateButton.Text = 'Install key and activate current edition'; $script:ActivateButton.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:ActivateButton.Size = New-Object System.Drawing.Size -ArgumentList 250, 34; $script:ActivateButton.Add_Click({ Start-CurrentEditionActivation }); $script:Form.Controls.Add($script:ActivateButton) $script:HomeProButton = New-Object System.Windows.Forms.Button; $script:HomeProButton.Text = 'Home to Pro via Windows Activation'; $script:HomeProButton.Location = New-Object System.Drawing.Point -ArgumentList 420, $y; $script:HomeProButton.Size = New-Object System.Drawing.Size -ArgumentList 250, 34; $script:HomeProButton.Enabled = $false; $script:HomeProButton.Add_Click({ Start-HomeToProFlow }); $script:Form.Controls.Add($script:HomeProButton) $y += 42 $script:PreflightCheckBox = New-Object System.Windows.Forms.CheckBox; $script:PreflightCheckBox.Text = 'Run connection preflight before activation'; $script:PreflightCheckBox.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:PreflightCheckBox.Size = New-Object System.Drawing.Size -ArgumentList 270, 24; $script:PreflightCheckBox.Checked = $true; $script:Form.Controls.Add($script:PreflightCheckBox) $script:FallbackCheckBox = New-Object System.Windows.Forms.CheckBox; $script:FallbackCheckBox.Text = 'Use slmgr fallback on failure'; $script:FallbackCheckBox.Location = New-Object System.Drawing.Point -ArgumentList 440, $y; $script:FallbackCheckBox.Size = New-Object System.Drawing.Size -ArgumentList 230, 24; $script:FallbackCheckBox.Checked = $true; $script:Form.Controls.Add($script:FallbackCheckBox) $y += 36 $script:CheckButton = New-Object System.Windows.Forms.Button; $script:CheckButton.Text = 'Check connection'; $script:CheckButton.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:CheckButton.Size = New-Object System.Drawing.Size -ArgumentList 138, 30; $script:CheckButton.Add_Click({ Show-ConnectivityChecks }); $script:Form.Controls.Add($script:CheckButton) $script:RefreshButton = New-Object System.Windows.Forms.Button; $script:RefreshButton.Text = 'Refresh'; $script:RefreshButton.Location = New-Object System.Drawing.Point -ArgumentList 308, $y; $script:RefreshButton.Size = New-Object System.Drawing.Size -ArgumentList 90, 30; $script:RefreshButton.Add_Click({ $script:CachedWindowsInfo = $null; Append-Log 'Refreshing Windows licensing info...'; Update-SystemInfo }); $script:Form.Controls.Add($script:RefreshButton) $script:SettingsButton = New-Object System.Windows.Forms.Button; $script:SettingsButton.Text = 'Activation Settings'; $script:SettingsButton.Location = New-Object System.Drawing.Point -ArgumentList 408, $y; $script:SettingsButton.Size = New-Object System.Drawing.Size -ArgumentList 124, 30; $script:SettingsButton.Add_Click({ Open-ActivationSettings }); $script:Form.Controls.Add($script:SettingsButton) $copyDiagButton = New-Object System.Windows.Forms.Button; $copyDiagButton.Text = 'Copy diagnostics'; $copyDiagButton.Location = New-Object System.Drawing.Point -ArgumentList 542, $y; $copyDiagButton.Size = New-Object System.Drawing.Size -ArgumentList 124, 30; $copyDiagButton.Add_Click({ Copy-Diagnostics }); $script:Form.Controls.Add($copyDiagButton) $script:BenchButton = New-Object System.Windows.Forms.Button; $script:BenchButton.Text = 'Phone active'; $script:BenchButton.Location = New-Object System.Drawing.Point -ArgumentList 676, $y; $script:BenchButton.Size = New-Object System.Drawing.Size -ArgumentList 94, 30; $script:BenchButton.Add_Click({ Start-PhoneActivationAssistant }); $script:Form.Controls.Add($script:BenchButton) $y += 50 $logLabel = New-Object System.Windows.Forms.Label; $logLabel.Text = 'Log'; $logLabel.AutoSize = $true; $logLabel.Location = New-Object System.Drawing.Point -ArgumentList 28, ($y + 4); $script:Form.Controls.Add($logLabel) $script:LogBox = New-Object System.Windows.Forms.TextBox; $script:LogBox.Location = New-Object System.Drawing.Point -ArgumentList 160, $y; $script:LogBox.Size = New-Object System.Drawing.Size -ArgumentList 610, 184; $script:LogBox.Multiline = $true; $script:LogBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical; $script:LogBox.ReadOnly = $true; $script:LogBox.Font = New-Object System.Drawing.Font -ArgumentList 'Consolas', 9; $script:Form.Controls.Add($script:LogBox) $script:StatusLabel = New-Object System.Windows.Forms.Label; $script:StatusLabel.Text = 'Loading...'; $script:StatusLabel.AutoSize = $false; $script:StatusLabel.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D; $script:StatusLabel.Location = New-Object System.Drawing.Point -ArgumentList 0, 624; $script:StatusLabel.Size = New-Object System.Drawing.Size -ArgumentList 804, 28; $script:StatusLabel.Anchor = [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right -bor [System.Windows.Forms.AnchorStyles]::Bottom; $script:StatusLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft; $script:Form.Controls.Add($script:StatusLabel) $script:Form.Add_Shown({ Append-Log 'Tool started with administrator permission.'; Update-SystemInfo; $script:KeyTextBox.Focus() }) [System.Windows.Forms.Application]::Run($script:Form)