<# Purpose Detect non ASCII characters in the signed in identity and, if found, set ACP OEMCP MACCP to 65001 Notes - Must run as Administrator - Changes require a reboot to fully apply - Creates a .reg backup and is idempotent #> # region Preconditions # Require elevation $IsAdmin = ([Security.Principal.WindowsPrincipal] ` [Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $IsAdmin) { Write-Error "Run this script in an elevated PowerShell session." exit 1 } # endregion # region Helpers function Test-HasNonAscii { param([Parameter(Mandatory)][string]$Text) return [bool]([regex]::IsMatch($Text, '[^\u0000-\u007F]')) } function Get-StringsToCheck { $list = New-Object System.Collections.Generic.List[string] # SAM style name $list.Add([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) # Local environment username and profile leaf if ($env:USERNAME) { $list.Add($env:USERNAME) } if ($env:USERPROFILE) { $list.Add([System.IO.Path]::GetFileName($env:USERPROFILE)) } # UPN when available try { $upn = (whoami /upn) 2>$null if ($upn -and $upn -notmatch '^\s*$' -and $LASTEXITCODE -eq 0) { $list.Add($upn.Trim()) } } catch { } # Entra display name when cached by IdentityCRL (best effort, may not exist) try { $idCrlRoot = 'HKCU:\Software\Microsoft\IdentityCRL\StoredIdentities' if (Test-Path $idCrlRoot) { Get-ChildItem $idCrlRoot -ErrorAction Stop | ForEach-Object { $dn = (Get-ItemProperty $_.PsPath -Name 'DisplayName' -ErrorAction SilentlyContinue).DisplayName if ($dn) { $list.Add($dn) } } } } catch { } # Distinct non empty strings return $list | Where-Object { $_ } | Select-Object -Unique } # endregion # region Detection $strings = Get-StringsToCheck $hasNonAscii = $false $hit = $null foreach ($s in $strings) { if (Test-HasNonAscii -Text $s) { $hasNonAscii = $true $hit = $s break } } if (-not $hasNonAscii) { Write-Output "No non ASCII characters detected in current identity strings. No registry change needed." exit 0 } Write-Output "Detected non ASCII characters in: $hit" # endregion # region Apply registry changes $regPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' $values = @('ACP','OEMCP','MACCP') $target = '65001' # Backup once $backupDir = 'C:\ProgramData\OneDriveUTF8Backup' $null = New-Item -Path $backupDir -ItemType Directory -Force -ErrorAction SilentlyContinue $backupFile = Join-Path $backupDir ('Nls_CodePage_{0:yyyyMMdd_HHmmss}.reg' -f (Get-Date)) try { & reg.exe export 'HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage' $backupFile /y | Out-Null Write-Output "Backup written to $backupFile" } catch { Write-Warning "Backup failed. Proceeding anyway. $_" } # Idempotency marker $marker = Join-Path $backupDir 'applied_65001.marker' # Compare current state $current = @{} foreach ($name in $values) { $v = (Get-ItemProperty -LiteralPath $regPath -Name $name -ErrorAction SilentlyContinue).$name $current[$name] = $v } $alreadySet = $values | ForEach-Object { $current[$_] -eq $target } | Where-Object { $_ -eq $false } | Measure-Object | Select-Object -ExpandProperty Count if ($alreadySet -eq 0 -and (Test-Path $marker)) { Write-Output "Registry already set to 65001 previously. Nothing to change." exit 0 } # Apply foreach ($name in $values) { New-ItemProperty -LiteralPath $regPath -Name $name -Value $target -PropertyType String -Force | Out-Null } # Mark Set-Content -Path $marker -Value ("Applied on {0:u}" -f (Get-Date)) -Encoding UTF8 Write-Output "ACP OEMCP MACCP set to 65001 successfully." Write-Output "A reboot is required for system wide code page changes to take effect." # Optional return code 3010 to signal reboot recommended to management tools $env:IMESignalReboot = "3010" exit 0 # endregion