Eswlnk Blog Eswlnk Blog
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈
  • 注册
  • 登录
首页 › 日志 › 「日志记录」一次 PowerShell UTF-8 配置脚本翻车排查

「日志记录」一次 PowerShell UTF-8 配置脚本翻车排查

Eswlnk的头像
Eswlnk
2026-03-09 0:40:22
「日志记录」一次 PowerShell UTF-8 配置脚本翻车排查-Eswlnk Blog
智能摘要 AI
本文探讨了在Windows环境下编写PowerShell脚本时常见的中文乱码及编码问题,并详细分析了其原因与解决方案。作者通过编写一个自动初始化Profile的脚本来解决乱码问题,但在执行时遇到了语法错误。经过排查发现,根本原因是脚本文件的编码格式不正确,而非简单的语法错误。 ### 核心问题 1. **PowerShell 5.1对UTF-8无BOM的支持不足**:在包含中文、emoji等特殊字符的情况下,PowerShell可能无法正确解析。 2. **源文件编码与输出文件编码不同**:脚本可以输出UTF-8无BOM文件,但源文件不一定适用。 ### 解决方案 1. **简化输出信息**:将含有emoji和中文的提示信息替换为纯ASCII字符,如`[OK]`和`[INFO]`,以减少编码问题。 2. **更改文件编码**:将`.ps

0x00 前言

编码问题,为什么报的是字符串缺少终止符?

在 Windows 上写 PowerShell 脚本时,很多人都会遇到中文乱码问题。为了让终端、文件输出都统一到 UTF-8,我们写了一个自动初始化 Profile 的脚本,目的是让 PowerShell 启动后默认使用 UTF-8 编码。

脚本逻辑本身并不复杂,但执行时却直接报了一个很“语法”的错误:

PS C:\Users\googl> C:\Users\googl\Desktop\1.ps1
所在位置 C:\Users\googl\Desktop\1.ps1:30 字符: 12
+ Write-Host "鈩癸笍 UTF-8 宸查厤缃紝璺宠繃銆? -ForegroundColor Cyan
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
字符串缺少终止符: "。
所在位置 C:\Users\googl\Desktop\1.ps1:29 字符: 8
+ } else {
+        ~
语句块或类型定义中缺少右“}”。
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

表面上看,这是一个典型的 PowerShell 语法错误:字符串没有闭合、右花括号缺失。但实际排查后发现,根因并不是语法,而是脚本文件本身的编码格式。

「日志记录」一次 PowerShell UTF-8 配置脚本翻车排查-Eswlnk Blog

0x01 问题背景

我们的原始脚本大致如下:

# Setup-UTF8PowerShellProfile.ps1
$utf8Config = @'
# 设置控制台使用 UTF-8 编码(无 BOM)
chcp 65001 | Out-Null
[Console]::InputEncoding  = [System.Text.UTF8Encoding]::new()
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
$OutputEncoding = [System.Text.UTF8Encoding]::new()
# 设置默认文件操作编码为 UTF-8(无 BOM)
$PSDefaultParameterValues['Out-File:Encoding']    = 'utf8'
$PSDefaultParameterValues['Set-Content:Encoding'] = 'utf8'
$PSDefaultParameterValues['Add-Content:Encoding'] = 'utf8'
'@
# 创建目录(如果不存在)
$profileDir = Split-Path -Parent $PROFILE
if (-not (Test-Path $profileDir)) {
New-Item -ItemType Directory -Path $profileDir -Force | Out-Null
}
# 读取现有内容
$existing = if (Test-Path $PROFILE) { Get-Content $PROFILE -Raw } else { "" }
# 检查是否已配置(避免重复)
$hasConfig = $existing -match 'Console::OutputEncoding' -and
$existing -match '\$OutputEncoding' -and
$existing -match "PSDefaultParameterValues.*Out-File:Encoding"
if (-not $hasConfig) {
$newContent = if ($existing) { "$existing`r`n$utf8Config" } else { $utf8Config }
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)  # $false = 无 BOM
[System.IO.File]::WriteAllText($PROFILE, $newContent, $utf8NoBom)
Write-Host "✅ UTF-8 配置已写入 Profile!路径: $PROFILE" -ForegroundColor Green
} else {
Write-Host "ℹ️ UTF-8 已配置,跳过。" -ForegroundColor Cyan
}
# 立即生效
. $PROFILE

它的设计目标很明确:

  1. 设置控制台输入输出为 UTF-8。
  2. 设置默认文件写入编码为 UTF-8。
  3. 自动写入 PowerShell Profile。
  4. 避免重复写入。
  5. 写完立即 . 加载生效。

按理说,这样的脚本不该出现语法问题。但现实是,一执行就炸。

0x02 现象分析:为什么明明代码没少引号,却提示字符串未结束?

最关键的异常信息其实是这一行:

Write-Host "鈩癸笍 UTF-8 宸查厤缃紝璺宠繃銆? -ForegroundColor Cyan

如果原始代码里写的是:

Write-Host "ℹ️ UTF-8 已配置,跳过。" -ForegroundColor Cyan

那现在输出成这串“乱码”,说明 PowerShell 在读取 .ps1 文件时,没有按正确编码解释脚本内容。

也就是说,PowerShell 看到的并不是我们编辑器里看到的那段源码,而是一段被错误解码后的文本。中文和 emoji 被破坏后,连字符串边界都可能被影响,最终导致解释器误判为:

  • 字符串缺少结束引号
  • else 所在的代码块没有正确闭合

所以这类报错虽然长得像语法问题,本质上其实是源码编码损坏导致的解析失败。

0x03 Windows PowerShell 5.1 对 UTF-8 无 BOM 并不友好

问题出现的根因,通常是以下组合导致的:

1. 脚本文件保存成了 UTF-8 无 BOM

很多现代编辑器默认喜欢把文件保存成 UTF-8 without BOM。这在大多数语言和工具链中没问题,但对 Windows PowerShell 5.1 来说,兼容性并不总是稳定。

PowerShell 5.1 对 .ps1 文件的编码识别比较老旧,尤其当文件里包含中文、emoji 或特殊符号时,如果没有 BOM,解析器可能会按 ANSI、本地代码页或其他错误方式去解释字节流。

2. 脚本里出现了中文和 emoji

这次最容易出问题的就是两行:

Write-Host "✅ UTF-8 配置已写入 Profile!路径: $PROFILE" -ForegroundColor Green
Write-Host "ℹ️ UTF-8 已配置,跳过。" -ForegroundColor Cyan

这里同时包含:

  • emoji:✅、ℹ️
  • 中文:配置已写入、跳过
  • 全角标点:!、:

这些字符一旦被错误解码,就很容易让整行字符串失真,甚至把结束引号也“污染”掉。

0x03 一个常见误区

这次问题还有一个很容易混淆的点:

我们脚本里确实是在主动把 Profile 写成 UTF-8 无 BOM:

$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($PROFILE, $newContent, $utf8NoBom)

这段逻辑本身没有问题。

但要注意:

  • 目标 Profile 文件写成 UTF-8 无 BOM,这是业务逻辑。
  • 当前 .ps1 脚本文件本身怎么保存,这是另一回事。

也就是说,你可以让脚本输出 UTF-8 无 BOM,但执行这个脚本的源文件本身,未必适合保存成 UTF-8 无 BOM,尤其是在 Windows PowerShell 5.1 下。

0x03 修复思路

针对这个问题,有两条非常实用的修复路径。

方案一:去掉高风险字符,尽量使用纯 ASCII 输出

这是最稳妥、最省事的做法。

把这些容易出编码问题的提示文字:

<span role="button" tabindex="0" data-code="Write-Host "✅ UTF-8 配置已写入 Profile!路径: $PROFILE" -ForegroundColor Green<br>Write-Host "ℹ️ UTF-8 已配置,跳过。" -ForegroundColor Cyan
Write-Host "✅ UTF-8 配置已写入 Profile!路径: $PROFILE" -ForegroundColor Green<br>Write-Host "ℹ️ UTF-8 已配置,跳过。" -ForegroundColor Cyan<br>

替换为纯英文或纯 ASCII:

Write-Host "[OK] UTF-8 config has been written to profile: $PROFILE" -ForegroundColor Green
Write-Host "[INFO] UTF-8 config already exists. Skipped." -ForegroundColor Cyan

这样即使编辑器、终端、PowerShell 对编码处理不一致,也不太容易炸。

修复后的完整脚本如下:

# Setup-UTF8PowerShellProfile.ps1

$utf8Config = @'
# Set console to UTF-8
chcp 65001 | Out-Null
[Console]::InputEncoding  = [System.Text.UTF8Encoding]::new()
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
$OutputEncoding = [System.Text.UTF8Encoding]::new()

# Set default file encodings to UTF-8
$PSDefaultParameterValues['Out-File:Encoding']    = 'utf8'
$PSDefaultParameterValues['Set-Content:Encoding'] = 'utf8'
$PSDefaultParameterValues['Add-Content:Encoding'] = 'utf8'
'@

# Create profile directory if needed
$profileDir = Split-Path -Parent $PROFILE
if (-not (Test-Path $profileDir)) {
    New-Item -ItemType Directory -Path $profileDir -Force | Out-Null
}

# Read existing profile
$existing = if (Test-Path $PROFILE) { Get-Content $PROFILE -Raw } else { "" }

# Check whether config already exists
$hasConfig = ($existing -match 'Console::OutputEncoding') -and
             ($existing -match '\$OutputEncoding') -and
             ($existing -match 'PSDefaultParameterValues.*Out-File:Encoding')

if (-not $hasConfig) {
    $newContent = if ($existing) { "$existing`r`n$utf8Config" } else { $utf8Config }

    # Write profile as UTF-8 without BOM
    $utf8NoBom = New-Object System.Text.UTF8Encoding($false)
    [System.IO.File]::WriteAllText($PROFILE, $newContent, $utf8NoBom)

    Write-Host "[OK] UTF-8 config has been written to profile: $PROFILE" -ForegroundColor Green
}
else {
    Write-Host "[INFO] UTF-8 config already exists. Skipped." -ForegroundColor Cyan
}

# Reload profile
. $PROFILE

方案二:保留中文,但把 .ps1 文件保存为 UTF-8 with BOM

如果确实想保留中文提示,那就尽量让 PowerShell 5.1 更容易正确识别脚本编码。

推荐做法是把脚本文件重新保存为 UTF-8 with BOM。

例如在 VS Code 中可以这样做:

  1. 打开脚本文件。
  2. 点击右下角当前编码。
  3. 选择“使用编码保存”。
  4. 选择 UTF-8 with BOM。

然后脚本内容可以保留中文,但建议仍然少用 emoji。

示例:

Write-Host "UTF-8 配置已写入 Profile:$PROFILE" -ForegroundColor Green
Write-Host "UTF-8 已配置,跳过。" -ForegroundColor Cyan

相比带 emoji 的版本,这样更稳。


0x04 为什么 PowerShell 7 一般没这么多坑?

如果你用的是 PowerShell 7+,很多 UTF-8 相关行为已经比 Windows PowerShell 5.1 现代得多,默认编码处理也更符合现在的开发习惯。

但现实问题在于:

  • 很多 Windows 机器默认还是 powershell.exe,也就是 5.1。
  • 许多运维脚本、登录脚本、企业环境初始化脚本仍然跑在 5.1 上。
  • 编辑器默认编码和运行时解析行为未必一致。

所以只要目标环境里还存在 PowerShell 5.1,就不能完全按“现代 UTF-8 习惯”来想当然。

0x05 这次排查带来的几个经验总结

1. 报语法错,不一定真是语法错

看到“字符串缺少终止符”“缺少右花括号”时,不要第一时间只盯着括号和引号数。

如果报错行里已经出现乱码,那优先怀疑:

  • 文件编码
  • 复制粘贴时的字符集损坏
  • 编辑器保存格式
  • 控制台或解释器解码方式

2. 源文件编码和输出文件编码是两回事

你可以让脚本把某个目标文件写成 UTF-8 无 BOM,但这不代表执行这个脚本的 .ps1 文件自己也适合无脑使用 UTF-8 无 BOM。

3. Windows PowerShell 5.1 下,尽量少在脚本源码里放 emoji

中文尚可控,emoji 风险更高。特别是在初始化脚本、部署脚本、登录脚本这种“必须稳”的地方,纯 ASCII 往往是更工程化的选择。

4. 做兼容性脚本时,输出消息尽量简单

这类基础设施脚本的重点是“稳定执行”,不是“漂亮展示”。像 [OK]、[INFO] 这种简单标记,在跨终端、跨编码环境中往往更可靠。

本站默认网盘访问密码:1166
本站默认网盘访问密码:1166
声明:本站原创文章文字版权归本站所有,转载务必注明作者和出处;本站转载文章仅仅代表原作者观点,不代表本站立场,图文版权归原作者所有。如有侵权,请联系我们删除。
开发日志日志记录
0
0
Eswlnk的头像
Eswlnk
一个有点倒霉的研究牲站长
赞赏
「日志」IG无缘S15总决赛
上一篇

评论 (0)

请登录以参与评论
现在登录
    发表评论

猜你喜欢

  • 「日志」IG无缘S15总决赛
  • 来自谷歌27岁的生日涂鸦
  • 插件分享:新增自助购买卡密功能
  • 事件记录:国内网络故障情况
  • 科研记录:ecCodes处理grib文件问题
Eswlnk的头像

Eswlnk

一个有点倒霉的研究牲站长
1109
文章
321
评论
682
获赞

随便看看

「日志记录」家庭监控方案:我的智能安防布局
2024-02-25 22:50:32
「开发日志」PoForge新一代跨平台PO翻译工具
2024-06-24 17:42:24
「日志记录」逆向必应翻译网页版API实现免费调用
2025-02-07 22:02:20

文章目录

专题展示

WordPress53

工程实践37

热门标签

360 AI API CDN java linux Nginx PDF PHP python SEO Windows WordPress 云服务器 云服务器知识 代码 免费 安全 安卓 工具 开发日志 微信 微软 手机 插件 攻防 攻防对抗 教程 日志 渗透分析 源码 漏洞 电脑 破解 系统 编程 网站优化 网络 网络安全 脚本 苹果 谷歌 软件 运维 逆向
  • 首页
  • 知识库
  • 地图
Copyright © 2023-2026 Eswlnk Blog. Designed by XiaoWu.
本站CDN由 壹盾安全 提供高防CDN安全防护服务
蜀ICP备20002650号-10
页面生成用时 0.631 秒   |  SQL查询 20 次
本站勉强运行:
友情链接: Eswlnk Blog 网站渗透 倦意博客 特资啦!个人资源分享站 祭夜博客 iBAAO壹宝头条
  • WordPress142
  • 网络安全64
  • 漏洞52
  • 软件52
  • 安全48
现在登录
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈