Tauri2】032 windows系统下的打包(二)
前言
前面简单地进行了打包
【Tauri2】031 windows系统下的打包-CSDN博客
https://blog.csdn.net/qq_63401240/article/details/147466278?spm=1001.2014.3001.5501遇到了bug,这篇就来解决一下。
正文
报错的解决
在目前的tauri的代码中,看看源码
log::info!(action = "Running"; "makensis to produce {}", display_path(&nsis_installer_path));
#[cfg(target_os = "windows")]
let mut nsis_cmd = Command::new(nsis_toolset_path.join("makensis.exe"));
#[cfg(not(target_os = "windows"))]
let mut nsis_cmd = Command::new("makensis");
if let Some(plugins_path) = &maybe_plugin_copy_path {
nsis_cmd.env("NSISPLUGINS", plugins_path);
}
nsis_cmd
.args(["-INPUTCHARSET", "UTF8", "-OUTPUTCHARSET", "UTF8"])
.arg(match settings.log_level() {
log::Level::Error => "-V1",
log::Level::Warn => "-V2",
log::Level::Info => "-V3",
_ => "-V4",
})
.arg(installer_nsi_path)
.env_remove("NSISDIR")
.env_remove("NSISCONFDIR")
.current_dir(output_path)
.piped()
.context("error running makensis.exe")?;
fs::rename(nsis_output_path, &nsis_installer_path)?;
首先执行日志,没问题
Running makensis to produce F:\Users\26644\RustProject\tb\src-tauri\target\release\bundle\nsis\tb_0.1.0_x64-setup.exe
然后获取nsis_cmd,本质是获取makensis.exe
接着添加参数与环境,字符集UTF8
其中installer_nsi_path 是固定的installer.nsi
let installer_nsi_path = output_path.join("installer.nsi");
write_utf8_with_bom(
&installer_nsi_path,
handlebars.render("installer.nsi", &data)?,
)?;
获取到这个文件然后渲染数据
如果使用默认模板,就渲染默认模板
如果是自定义,比如tb.nsi,就会把tb.nsi中的内容渲染到其中
实际上,可以发现
tb.nsi和installer.nsi一模一样
执行installer_nsi_path。
即F:\Users\26644\RustProject\tb\src-tauri\target\release\nsis\x64\installer.nsi
这前面其实都没有问题
下面这一步就出现了问题
fs::rename(nsis_output_path, &nsis_installer_path)?;
进行了rename。
这个nsis_installer_path 本质上就是前面打印语句的输出的路径
let nsis_installer_path = settings.project_out_directory().to_path_buf().join(format!(
"bundle/{}/{}.exe",
if updater {
NSIS_UPDATER_OUTPUT_FOLDER_NAME
} else {
NSIS_OUTPUT_FOLDER_NAME
},
package_base_name
));
而这个nsis_output_path,就是指输出文件
可以看到是一个output_path+out_file
let nsis_output_path = output_path.join(out_file);
而这个out_file在源代码如下
let out_file = "nsis-output.exe";
data.insert("out_file", to_json(out_file));
是写死的。这一步是有问题,因此,可以得出报错的原因
代码中希望找到nsis-output.exe,但是笔者是自定义的输出名字——setup.exe,有问题
因此,修改打包输出即可
OutFile "nsis-output.exe"
这一步居然是固定的。只能写成这个。
代码是这么写的。。。
运行没有问题

简单使用handlebars
It uses handlebars so the Tauri CLI can brand your installer according to your tauri.conf.json
——Tauri官网
前面渲染模板使用的模板引擎就是handlebars,
handlerbar是JavaScript 的模板引擎,将模板编译为 JavaScript 函数。
但是也有Rust版本的handlebars - Rust
https://docs.rs/handlebars/latest/handlebars/
新建一个crate test-handlerbar,试试使用这个模板引擎。
注册依赖
[dependencies]
handlebars={version = "6.3.2"}
serde_json= {version = "1"}
简单的使用
use handlebars::{Handlebars};
use serde_json::json;
fn render() {
let mut reg = Handlebars::new();
reg.register_template_string(
"render-id","
Hello {{name}}"
).unwrap();
let data = json!({
"name": "world",
});
let rendered = reg.render("render-id", &data).unwrap();
println!("{}", rendered);
}
fn main() {
render()
}
内容其实很简单,
很明显,register_template_string这个函数,第一个参数传一个"id",第二个参数就是模板字符串。后面根据"id"渲染,以 {{}} 作为标准,替换里面的内容。
读取文件再渲染
目录结构如下

读取fixture中的a.nsi,保存到result目录下,代码如下
use handlebars::{Handlebars};
use serde_json::json;
use std::fs;
fn render() -> Result<(), Box<dyn std::error::Error>> {
let mut reg = Handlebars::new();
// 读取模板文件内容
let template_content = fs::read_to_string("fixture/a.nsi")?;
reg.register_template_string("render-id", &template_content)?;
// 读取数据文件内容
let data = json!({
"product_name": "tb",
});
let rendered = reg.render("render-id", &data)?;
println!("{}", rendered);
let output_file = "result/res_a.nsi";
fs::write(output_file, rendered)?;
Ok(())
}
fn main() {
render();
}
渲染前的文件内容
!define PRODUCT_NAME "{{product_name}}"
渲染后
!define PRODUCT_NAME "tb"
实际上就可以操作了
与tauri项目连用
一些关于NSIS的参考
NSIS 从入门到编写完整打包脚本——2024/12/02NSIS是功能强大的安装包制作工具,但其高质量的教程稀少,上手 - 掘金
https://juejin.cn/post/7207410405857034301根据tb.nsi建立属于自己的模板文件,比如说叫installer.nsi
fixture/installer.nsi的内容如下
; Script generated by the HM NIS Edit Script Wizard.
; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "{{product_name}}"
!define PRODUCT_VERSION "{{product_version}}"
!define PRODUCT_PUBLISHER "{{product_publisher}}"
!define PRODUCT_WEB_SITE "{{product_web_site}}"
!define PRODUCT_PATH_BEFORE "{{product_path_before}}"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\{{product_name}}.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
!include "MUI.nsh"
; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "${PRODUCT_PATH_BEFORE}/${PRODUCT_NAME}/src-tauri/icons/icon.ico"
!define MUI_UNICON "{{#with uninstall_icon}}{{this}} {{else}}${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico{{/with}}"
; Welcome page
!insertmacro MUI_PAGE_WELCOME
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Start menu page
var ICONS_GROUP
!define MUI_STARTMENUPAGE_NODISABLE
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${PRODUCT_NAME}"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_NAME}.exe"
!insertmacro MUI_PAGE_FINISH
; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES
; Language files
!insertmacro MUI_LANGUAGE "English"
; MUI end ------
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "nsis-output.exe"
InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show
Section "MainSection" SEC01
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File "${PRODUCT_PATH_BEFORE}\${PRODUCT_NAME}\src-tauri\target\release\${PRODUCT_NAME}.exe"
; Shortcuts
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd
Section -AdditionalIcons
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe"
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd
Section -Post
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${PRODUCT_NAME}.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_NAME}.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 删除成功"
FunctionEnd
Function un.onInit
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "确实删除 $(^Name) 所有内容吗" IDYES +2
Abort
FunctionEnd
Section Uninstall
!insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
Delete "$INSTDIR\${PRODUCT_NAME}.url"
Delete "$INSTDIR\uninst.exe"
Delete "$INSTDIR\${PRODUCT_NAME}.exe"
Delete "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk"
Delete "$SMPROGRAMS\$ICONS_GROUP\Website.lnk"
Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
Delete "$SMPROGRAMS\$ICONS_GROUP\${PRODUCT_NAME}.lnk"
RMDir "$SMPROGRAMS\$ICONS_GROUP"
RMDir "$INSTDIR"
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
SetAutoClose true
SectionEnd
内容可以根据实际需要修改。
笔者设置 product_name、product_version、product_publisher、product_web_site
和product_path_before,看个人需求。无所谓。
product_path_before笔者想的是,比如说,建立一个tb目录。路径在xxx/xx/xxx/tb
其中xxx/xx/xxx/就是指product_path_before
product_name就是项目的名字,
笔者使用src-tauir下的默认的icon.ico。
输出的安装包笔者固定nsis-output.exe
其他无关紧要
渲染的关键代码
let template_content = fs::read_to_string("fixture/installer.nsi")?;
reg.register_template_string("render-id", &template_content)?;
let name="tb";
let data = json!({
"product_name": name,
"product_version":"1.0.0",
"product_publisher":"you",
"product_web_site":"https://www.baidu.com",
"product_path_before":"F:/Users/26644/RustProject"
});
let rendered = reg.render("render-id", &data)?;
let output_file = format!("result/{}.nsi", name);
运行后生成tb.nsi,笔者通过NSIS edit编译运行,生成了nsis-output.exe,可以安装,没问题。

笔者是Windows操作系统,其他操作系统类似的,随机应变。
怎么在运行build命令的时候生成对应项目的nsi文件?
pnpm run tauri build
这其实很简单,在src-tauri目录下有build.rs,写在下面这行代码之前就可以
tauri_build::build()
在Cargo.toml文件中
[build-dependencies]
tauri-build = { version = "2", features = [] }
serde_json = "1"
handlebars= {version = "6.3.2"}
运行命令,结果成功。
实际上还可以更进一步,这些参数都可以获取的,通过toml文件。这就不细说了。
修改图标
这没什么好说的,直接运行命令 pnpm tarui icon + 图片路径

有点要求
Source image must be square
Error Source image must be square
运行成功
➜ pnpm tauri icon "C:\Users\26644\Downloads\124107496_p0_resized.jpg"
> tb@0.1.0 tauri F:\Users\26644\RustProject\tb
> tauri "icon" "C:\\Users\\26644\\Downloads\\124107496_p0_resized.jpg"
.....
此时icon.ico文件就变成所需要的图片。

总结
截止到目前,使用NSIS打包,没有配置自定义模板的情况下,
先使用handlebars渲染默认的installer.nsi文件,生成渲染后的installer.nsi
然后通过makensis.exe渲染后的installer.nsi,生成nsis-output.exe文件,修改nsis-output.exe的名字和路径。放在在target/release/bundle/nsis目录下。就这样操作的。
没有使用默认的文件,使用自定义的模板,还是一样的,最后渲染后的文件是installer.nsi。
其他不变。
更多推荐


所有评论(0)