在 Windows 上以 UTF-8 (Code Page 65001) 运行任意可执行文件的轻量级启动器。
在 Windows 上使用 MSVC 编译 llama-cpp-python 等含有非 ASCII 字符的 C/C++ 项目时,经常会因为系统默认代码页 (如 GBK / CP936) 导致各种编码错误——源文件中的 UTF-8 字符串被截断、编译器报 C2001 / C2143、链接器路径解析失败等等。
UTF-8 Emulator 通过 DLL 注入技术,在目标进程启动前将活动代码页 (ACP) 劫持为 65001 (UTF-8),从根源上解决这一问题。无需修改系统区域设置,也无需开启 Windows 的 Beta 版 UTF-8 全局选项。
LEProc64.exe cl.exe /nologo /utf-8 hello.cpp
│
├─ 1. 解析目标路径 (模拟 Windows PATH 查找逻辑)
├─ 2. 读取 PE 头,检测目标架构 (x86 / x64)
│ └─ 架构不匹配时自动委派给 LEProc32.exe 或 LEProc64.exe
├─ 3. 以 CREATE_SUSPENDED 创建目标进程
├─ 4. 通过 CreateRemoteThread + LoadLibraryW 注入 LRHook DLL
│ └─ DLL 内部 hook GetACP()、GetOEMCP() 等 API,返回 65001
├─ 5. 设置环境变量 (LRCodePage=65001, LRLCID, LRBIAS)
├─ 6. ResumeThread,目标进程在 UTF-8 环境下正常执行
└─ 7. 等待退出,透传 exit code
从 Releases 下载预编译包,解压后确保以下文件在同一目录:
LEProc32.exe
LEProc64.exe
LRHookx32.dll
LRHookx64.dll
LEProc64.exe <目标程序> [参数...]示例:用 MSVC 编译含中文注释的源文件
LEProc64.exe cl.exe /nologo /utf-8 hello.cpp示例:运行 pip install(编译 llama-cpp-python)
LEProc64.exe pip install llama-cpp-python示例:运行 CMake + Ninja 构建
LEProc64.exe cmake --build build --config Release程序会自动检测目标的架构——即使你用 LEProc64.exe 启动一个 32 位程序,它也会自动委派给 LEProc32.exe 处理。
- Visual Studio 2022+ 或
dotnetCLI - .NET Framework 4.8 SDK
dotnet build -c Release -p:Platform=x64
dotnet build -c Release -p:Platform=x86输出位于 out/Release/ 目录。
Utf8Emulator.slnx # Visual Studio 解决方案
LEProc/
├── Program.cs # 主程序:进程创建、DLL 注入、架构委派
├── LEProc.csproj # 项目配置 (双平台: x86/x64)
├── LRHookx32.dll # 32 位 hook DLL (来自 Locale Remulator)
└── LRHookx64.dll # 64 位 hook DLL (来自 Locale Remulator)
Runner/
└── Runner.cs # 诊断工具:打印当前代码页信息
out/Release/ # 编译产物
Windows 的 Beta 选项是全局的,会修改整个系统的 ACP,可能导致旧版软件出现兼容性问题。UTF-8 Emulator 只对目标进程生效,不影响系统其他部分。
chcp 65001 只影响当前控制台窗口的代码页,对通过 CreateProcessW 创建的子进程无效。UTF-8 Emulator 通过 DLL 注入在 API 层面进行 hook,确保目标进程及其子进程的 GetACP() 等调用均返回 65001。
DLL 注入是合法的 Windows 编程技术,但部分杀毒软件可能会误报。如遇拦截,请将 LEProc 及 LRHook DLL 加入信任列表。
- Locale Remulator — 本项目使用的 Hook DLL (
LRHookx32.dll/LRHookx64.dll) 来自 Locale Remulator 项目。感谢 @InWILL 及所有贡献者的出色工作。
本项目中包含的 LRHookx32.dll 和 LRHookx64.dll 来自 Locale Remulator,遵循其原始许可证 (LGPL-3.0)。