# Force true UTF-8 body (not GBK) with BOM; ASCII-only script $ErrorActionPreference = 'Stop' $path = 'E:\wwwroot\.env' $bak = 'E:\wwwroot\.env.bak-encoding2-' + (Get-Date -Format 'yyyyMMdd-HHmmss') Copy-Item $path $bak -Force function U([string]$escaped) { return [System.Text.RegularExpressions.Regex]::Unescape($escaped) } # Read previous values using BOTH encodings; prefer lines that parse as KEY=VALUE ascii function Load-Map([byte[]]$bytes) { $map = [ordered]@{} foreach ($encName in @('utf-8', 'gbk')) { $enc = if ($encName -eq 'utf-8') { New-Object System.Text.UTF8Encoding $false } else { [System.Text.Encoding]::GetEncoding(936) } $start = 0 if ($bytes.Length -ge 3 -and $bytes[0] -eq 239 -and $bytes[1] -eq 187 -and $bytes[2] -eq 191) { $start = 3 } $text = $enc.GetString($bytes, $start, $bytes.Length - $start) foreach ($line in ($text -split "`r?`n")) { $t = $line.Trim() if (-not $t -or $t.StartsWith('#')) { continue } $i = $t.IndexOf('=') if ($i -lt 1) { continue } $k = $t.Substring(0, $i).Trim() $v = $t.Substring($i + 1) if ($k -notmatch '^[A-Z0-9_]+$') { continue } if (-not $map.Contains($k)) { $map[$k] = $v } } } return $map } $bytes = [System.IO.File]::ReadAllBytes($path) $map = Load-Map $bytes Write-Output ('keys=' + $map.Count) $goodReply = U '\u8be2\u4ef7\u667a\u80fd\u4f53\u63a5\u901a\u6210\u529f\u3002\u5df2\u6536\u5230\uff1a{content}' $map['WECOM_CALLBACK_REPLY_TEXT'] = $goodReply function V([string]$k, [string]$d = '') { if ($map.Contains($k)) { return [string]$map[$k] } return $d } $lines = New-Object System.Collections.Generic.List[string] $lines.Add((U '# \u53cb\u901a\u8fbe\u8be2\u4ef7\u667a\u80fd\u4f53 \u00b7 \u73af\u5883\u53d8\u91cf\uff08E:\\wwwroot\\.env\uff09')) $lines.Add((U '# \u7f16\u7801 UTF-8 BOM\uff1b\u8bb0\u4e8b\u672c\u8bf7\u9009 UTF-8\u3002\u7981\u6b62\u63d0\u4ea4 Git\u3002')) $lines.Add((U '# \u5bf9\u7167 prompt/13')) $lines.Add('') $lines.Add('YTD_ENV=' + (V 'YTD_ENV' 'test')) $lines.Add('') $lines.Add((U '# \u516c\u7f51\u4e0e\u4f01\u5fae')) $lines.Add('PUBLIC_BASE_URL=' + (V 'PUBLIC_BASE_URL')) $lines.Add('WECOM_CALLBACK_URL=' + (V 'WECOM_CALLBACK_URL')) $lines.Add('INQUIRY_FORM_PUBLIC_BASE_URL=' + (V 'INQUIRY_FORM_PUBLIC_BASE_URL')) $lines.Add('WECOM_CORP_ID=' + (V 'WECOM_CORP_ID')) $lines.Add('WECOM_AGENT_ID=' + (V 'WECOM_AGENT_ID')) $lines.Add('WECOM_SECRET=' + (V 'WECOM_SECRET')) $lines.Add('WECOM_CALLBACK_TOKEN=' + (V 'WECOM_CALLBACK_TOKEN')) $lines.Add('WECOM_ENCODING_AES_KEY=' + (V 'WECOM_ENCODING_AES_KEY')) $lines.Add('WECOM_CALLBACK_REPLY_TEXT=' + $goodReply) $lines.Add('WECOM_OPS_AGENT_ID=' + (V 'WECOM_OPS_AGENT_ID')) $lines.Add('DEV_INJECT_ENABLED=' + (V 'DEV_INJECT_ENABLED' 'false')) $lines.Add('') $lines.Add((U '# \u5176\u4f59\u914d\u7f6e')) $skip = @('YTD_ENV','PUBLIC_BASE_URL','WECOM_CALLBACK_URL','INQUIRY_FORM_PUBLIC_BASE_URL','WECOM_CORP_ID','WECOM_AGENT_ID','WECOM_SECRET','WECOM_CALLBACK_TOKEN','WECOM_ENCODING_AES_KEY','WECOM_CALLBACK_REPLY_TEXT','WECOM_OPS_AGENT_ID','DEV_INJECT_ENABLED') foreach ($k in $map.Keys) { if ($skip -contains $k) { continue } $lines.Add($k + '=' + $map[$k]) } $text = [string]::Join("`r`n", $lines.ToArray()) + "`r`n" # Write UTF-8 BOM explicitly via bytes $utf8 = New-Object System.Text.UTF8Encoding $false $body = $utf8.GetBytes($text) $bom = [byte[]](0xEF, 0xBB, 0xBF) $all = New-Object byte[] ($bom.Length + $body.Length) [Array]::Copy($bom, 0, $all, 0, 3) [Array]::Copy($body, 0, $all, 3, $body.Length) [System.IO.File]::WriteAllBytes($path, $all) # Prove first Chinese char "友" is UTF-8 E5 8F 8B not GBK D3 D1 $nb = [System.IO.File]::ReadAllBytes($path) # find first non-ascii after BOM $i = 3 while ($i -lt $nb.Length -and $nb[$i] -lt 128) { $i++ } $hex = ($nb[$i..([Math]::Min($i+2, $nb.Length-1))] | ForEach-Object { $_.ToString('X2') }) -join ' ' Write-Output ('first_non_ascii_hex=' + $hex) Write-Output ('expect_utf8_you=E5 8F 8B') Write-Output ('is_utf8_you=' + ($hex -eq 'E5 8F 8B')) # decode check without console encoding issues: look for UTF-8 sequence of 询 $needle = $utf8.GetBytes((U '\u8be2\u4ef7')) $found = $false for ($p = 0; $p -le $nb.Length - $needle.Length; $p++) { $ok = $true for ($j = 0; $j -lt $needle.Length; $j++) { if ($nb[$p + $j] -ne $needle[$j]) { $ok = $false; break } } if ($ok) { $found = $true; break } } Write-Output ('has_utf8_xunjia=' + $found) Write-Output 'ENV_UTF8_OK'