一、背景
开发的桌面应用要求对应用名称进行多语言个性化:
-
支持多语言安装环境:
- 中文环境生成程序入口为
中文应用.exe - 其他语言环境生成程序入口为
AppEN.exe
- 中文环境生成程序入口为
-
安装包在安装后,快捷方式、任务管理器显示的进程名需对应语言环境。
-
用户数据、SharedPreferences(SP)、数据库等持久化存储路径需保持一致,不随程序入口名称变化,保证原有逻辑不受干扰,最小程度侵入;
-
CI/CD 流程基于 Jenkins,需要支持远程自动打包。
二、遇到的问题记录
1. NSIS 中文语句报错
最初尝试在 NSIS 脚本中直接使用中文程序名:
OutFile "中文应用.exe"
CreateShortCut "$DESKTOP\中文应用.lnk" "$INSTDIR\中文应用.exe"
或者直接重命名 exe
File "${EXE_NAME}"
Rename "$INSTDIR\${EXE_NAME}" "$INSTDIR\中文应用.exe"
问题现象:
- 本地编译正常,但 Jenkins 执行构建时失败
- 错误信息多为 “Invalid character set” 或找不到文件
原因分析:
- NSIS 默认 ANSI 编码,如果脚本中包含中文字符,在英文系统或 Jenkins 执行环境(通常非中文)下无法正确解析
- 中文字符可能在 UTF-8 或系统默认编码下被误处理,导致编译失败
2. CMake 多 EXE 输出
尝试在 CMake 中配置多程序入口:
cmake_minimum_required(VERSION 3.15)
project(MyApp)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# 原始可执行文件
add_executable(myapp main.cpp)
# 生成多语言版本(仅重命名副本,避免在 NSIS 内部硬编码中文)
add_custom_command(TARGET myapp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:myapp> ${CMAKE_BINARY_DIR}/bin/myapp_en.exe
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:myapp> ${CMAKE_BINARY_DIR}/bin/myapp_zh.exe
)
问题现象:
- 构建阶段可以生成多个 EXE(
中文应用.exe和English App.exe) - 安装界面文本仍然固定
- 程序启动及任务管理器显示名称不稳定
- SP、数据库等存储路径未受影响,但在某些安装目录下出现权限或访问异常
原因分析:
- CMake 对
RUNTIME_OUTPUT_NAME的编码依赖系统环境,中文名称在 Jenkins 或英文环境下可能无法正确生成 - 即便 EXE 成功生成,NSIS 拷贝或快捷方式创建过程中仍可能因中文文件名报错
3. CMake 多 EXE 输出 + LangString
Tips
安装界面多语言采用 NSIS 官方推荐的 LangString 机制:
Reference/LangString - NSIS
LangString定义一组以 语言 ID 区分的字符串常量- 在运行时,NSIS 会根据用户选择的安装语言自动切换对应的字符串
- 使用时通过
$(变量名)引用,而不是直接写死在脚本里
具体实现
根据安装平台拷贝 exe
${If} $LANGUAGE == ${LANG_SIMPCHINESE}
File /oname=$(EXE_NAME_LOCALIZED) "..\build\windows\x64\runner\${BT}\中文应用.exe"
${ElseIf} $LANGUAGE == ${LANG_TRADCHINESE}
File /oname=$(EXE_NAME_LOCALIZED) "..\build\windows\x64\runner\${BT}\中文应用.exe"
${Else}
File /oname=$(EXE_NAME_LOCALIZED) "..\build\windows\x64\runner\${BT}\AppEN.exe"
${EndIf}
安装界面多语言
!include MUI2.nsh
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "SimpChinese"
; 定义不同语言下的应用名称
LangString APP_NAME ${LANG_ENGLISH} "AppEN"
LangString APP_NAME ${LANG_SIMPCHINESE} "我的应用"
Section "Install"
; 在快捷方式创建中引用 LangString
CreateShortcut "$DESKTOP\$(APP_NAME).lnk" "$INSTDIR\myapp.exe"
SectionEnd
效果验证:
- 不论 Jenkins 或本地环境,NSIS 编译均可通过
- 安装后,中文系统显示
中文应用.exe,英文系统显示AppEN.exe - 任务管理器显示名称符合语言环境
- 用户 SP、数据库路径保持不变,不受 EXE 重命名影响
原因分析:
LangString内部使用 Unicode 编码,支持多语言环境安全解析- 避免了在 NSIS 脚本中直接书写中文字符,兼容 Jenkins 的英文系统环境
4.应用图标在大图标模式不友好
原因
-
Flutter Windows 构建图标
- Flutter 默认使用一个
app_icon.ico(或者runner.rc指定)作为应用图标。 - 如果你的
ico文件里只包含 256x256 或 48x48 的单一尺寸,那么在桌面 大图标模式 (256x256) 下,Windows 会拉伸/缩放 → 模糊。
- Flutter 默认使用一个
-
桌面快捷方式图标
- 快捷方式
.lnk默认会引用安装目录的 EXE 内置图标。 - 如果该图标缺少 16x16 / 32x32 / 48x48 / 128x128 / 256x256 等多尺寸,Windows 会自动缩放,显示效果差。
- 快捷方式
解决
使用 ImageMagick 对原始图标进行转换,满足多分辨率需求
安装 ImageMagick(Windows)
-
下载 Windows binary release(推荐 ImageMagick-7.x.x-Q16-HDRI-x64-dll.exe 安装包)。
-
安装时勾选:
- ✅ Add application directory to your system path
- ✅ Install legacy utilities (e.g. convert)
这样安装完后,你就可以在
cmd 或 PowerShell 里直接运行 magick。
生成多分辨率 ICO
假设你有 app.png,在终端执行:
magick app.png -define icon:auto-resize=16,24,32,48,64,128,256 app.ico
生成的 app.ico 就包含多个分辨率,Windows 桌面 / 任务栏 / 文件管理器都会自动挑合适的尺寸显示。
三、最终构建流程
flowchart TD
A["用户运行安装程序"] --> B["NSIS 检测系统语言($LANGUAGE)"]
B --> C{"语言判断分支"}
C -->|LANG_SIMPCHINESE| D["选择 '中文应用.exe'"]
C -->|LANG_ENGLISH默认| F["选择 'AppEN.exe'"]
D --> G["LangString 动态设置界面文本和文件名"]
F --> G
G --> H["File /oname=$(EXE_NAME_LOCALIZED)\n复制对应 exe"]
H --> I["创建快捷方式\n$(PRODUCT_NAME_LOCALIZED).lnk"]
-
Flutter build
- 执行
flutter build windows,生成默认 EXE。 - 使用 CMake 配置生成多语言输出(可选,作为中间文件管理)。
- 执行
-
NSIS 安装包生成
- 脚本中使用
LangString定义不同语言的 EXE 名称。 - 拷贝构建生成的 EXE,并在安装目录重命名。
- 创建语言对应的快捷方式。
- 脚本中使用
-
持久化数据路径管理
- Flutter 应用中 SP、数据库路径固定使用
AppData\Roaming\MyApp或其他固定路径。 - 重命名 EXE 不影响数据访问。
- Flutter 应用中 SP、数据库路径固定使用
-
Jenkins CI/CD
- Jenkins 执行 NSIS 脚本时,无需额外修改系统语言环境。
- 编译流程全程 Unicode 安全。
四、总结与建议
graph TD
A[Flutter项目] --> B[flutter build windows]
B --> C[CMake配置]
C --> D[生成两个exe: AppEN.exe & AppCN.exe]
D --> E[NSIS安装脚本]
E --> F{系统语言环境判断}
F -->|中文环境| G[设置名称为 中文命名.exe]
F -->|其他语言| H[设置名称为 AppEN.exe]
G --> I[拷贝文件到安装目录]
H --> I
I --> J[创建桌面快捷方式]
J --> K[保持用户数据路径一致性]
K --> L[安装完成]
%% 问题说明
M[NSIS中文命名兼容性问题] --> D
N[多exe生成配置] --> C
O[LangString多语言解决方案] --> F
- NSIS 不直接使用中文字符:避免编码问题,特别是 CI/CD 英文系统环境。
- 使用 LangString 实现多语言文件名:安全可靠,支持简繁中文及英文。
- CMake 输出多 EXE 可选:主要用于本地或调试环境,生产安装包依赖 NSIS 重命名更稳定。
- 持久化路径固定:保证用户数据、SP、数据库不随 EXE 名称变化,提升跨语言环境兼容性。
- CI/CD 环境安全:Unicode + LangString 可以在 Jenkins 英文系统下顺利打包。