前言
使用Tauri2+前端,本质是进程间的通信。并非前后端。
而想使用nw,先后端打包exe,再和前端打包成exe,并没有完成成功。
而笔者从Tauri中看到这种可能性。很有可能成功基于SeaORM+MySQL+Tauri2+Vite+React等的CRUD交互项目-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146273043在github action工作流使用nw和nw-builder打包-CSDN博客
https://blog.csdn.net/qq_63401240/article/details/146126489?spm=1001.2014.3001.5502
正文
建立tq项目

在前面的基础上。不必细说
直入主题
关键插件
@tauri-apps/plugin-shell | Tauri - Tauri 框架https://v2.tauri.org.cn/reference/javascript/shell/这个插件,可以在Rust运行cmd,也可以在JS中运行。
后端打包成exe,比如manage.exe,应该放到什么位置?这值得思考
一段代码的启示
笔者在下面这段代码发现,打印resolveResource
import {resolveResource} from '@tauri-apps/api/path'
console.log(await resolveResource())
// F:\Users\26644\webstormProject\tq\src-tauri\target\debug
结果是xxxx/xxx/target/debug。
看到这里,笔者直觉感觉到放debug目录下。
进入debug目录,笔者发现了tq.exe

第二段代码的启示
在tauri2的官网关于shell的例子
Shell | Taurihttps://v2.tauri.app/zh-cn/plugin/shell/例子如下
JS代码
import { Command } from '@tauri-apps/plugin-shell';
// 当设置 `"withGlobalTauri": true`, 你可以使用
// const { Command } = window.__TAURI__.shell;
let result = await Command.create('exec-sh', [
'-c',
"echo 'Hello World!'",
]).execute();
console.log(result);
Rust许可
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-capability",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "exec-sh",
"cmd": "sh",
"args": [
"-c",
{
"validator": "\\S+"
}
],
"sidecar": false
}
]
}
]
}
代码的目的就是在sh中打印hello world。
在许可中
name:exec-sh是名字,正是第一次参数
-c:对应-c
在许可中
validator是校验器,后面的正则表达式的意思是输入的字符串必须包含至少一个非空白字符
因此,笔者模仿了代码。
许多次尝试之后
1、将manage.exe放到debug目录下
2、前端的代码如下
import { Command } from '@tauri-apps/plugin-shell';
async function startDjangoServer() {
try {
console.log('Starting DjangoServer');
// 关键代码
let result = await Command.create("jango").execute();
// 如果执行成功,直接阻塞,不会打印下面的语句
console.log('Django server started successfully:', result);
} catch (error) {
console.log(error)
console.error('Failed to start Django server:', error);
}
}
export default startDjangoServer;
3、许可如下
"permissions": [
"core:default",
"opener:default",
"core:window:allow-show",
"core:window:allow-hide",
"dialog:default",
"shell:default",
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "jango",
"cmd": "powershell",
"args": [
"manage.exe runserver --noreload"
],
"sidecar": false
}
]
}
]
名字叫jango。
在powershell中。
运行参数 manage.exe runserver --noreload
运行
在没有运行项目前,端口号8000确实是关闭的

运行项目
刚开始

还没有完全启动,等了一会

完美,看8000端口号

不好的点
如果此时打开任务管理器,搜索manage.exe。
结果如下

可以发现,有多个exe,
笔者猜测是在前端React的组件中运行的,React组件渲染过程中,多次调用了前面的js代码,而且每次刷新页面,都会增加几个exe。
既然如此,笔者把启动manage.exe的代码写在Tauri中,
其实笔者并不是很甘心,一直询问AI,看看官网,无论是单例模式,还是React-Redux或者其他东西,都尝试过,每次刷新页面,都会新增manage.exe。无可奈何,只能写在Tauri中。
在Tauri中的尝试
希望的逻辑如下。
1、开始的时候,连接exe。
2、关闭的时候,断开exe。
实际的代码
rust
use tauri::Manager;
use tauri::WindowEvent;
use tauri_plugin_shell::ShellExt;
use std::sync::Mutex;
use std::process::Command;
struct DjangoState {
pid: Option<u32>, // 存储 Django 服务的 PID
}
fn is_manage_exe_running() -> bool { // 判断manage.exe 是否在运行
let output = Command::new("tasklist")
.args(&["/FI", "IMAGENAME eq manage.exe"])
.output();
match output {
Ok(output) => {
let stdout = String::from_utf8_lossy(&output.stdout);
stdout.contains("manage.exe")
}
Err(_) => false,
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_shell::init()) // 初始化 shell 插件
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_opener::init())
.manage(Mutex::new(DjangoState { pid: None })) // 初始化状态
.setup(|app| {
// 获取状态
let state = app.state::<Mutex<DjangoState>>();
// 检查是否已经启动
let mut state = state.lock().unwrap();
if state.pid.is_none() {
// 检查 manage.exe 是否已经在运行
if is_manage_exe_running() {
println!("manage.exe is already running.");
} else {
// 启动 Django 服务
let shell = app.shell();
let result = shell
.command("powershell") // 或者 "manager.exe",确保路径正确
.args(["manage.exe", "runserver", "--noreload"])
.spawn();// 返回Result<(Receiver<CommandEvent>, CommandChild)>
match result {
Ok((_receiver, child)) => {
let pid = child.pid();
println!("Django server started with PID: {}", pid);
// 存储 PID
state.pid = Some(pid);
}
Err(err) => {
println!("Failed to start Django server: {:?}", err);
}
}
}
}
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
实际情况 ,笔者无法终结exe,首先,没有管理员权限。
其次,有bug
显示打开的是

PID是14588,然而,打开任务管理器

什么情况????????
为什么有两个,为什么PID不对?
笔者也找不到原因
运行没有bug,可以获得数据。
因此,实际的逻辑
1、查看是否有manage.exe在运行
2、有则跳过,没有则打开
很明显,不是很好,假如有其他的exe,也叫manage.exe,就G了。
但又不得不这样做,可以运行。
