Tauri应用执行bat脚本时CMD窗口闪烁问题求解
解决Tauri中运行bat文件时CMD窗口一闪而过的问题
在Tauri应用中通过Rust的std::process::Command执行bat/cmd脚本时,会出现黑色CMD控制台窗口一闪而过的现象,示例代码中的关键执行逻辑如下:
let output = Command::new("cmd").args(["/C", &profile_path, "&", "echo", &env_flag, "&", "set"]).output().expect("process failed to execute");
完整代码:
extern crate mount_dir; extern crate random_string; use std::env::{set_var}; use std::process::Command; use std::fs::{remove_dir_all}; use std::path::{Component, Path}; use std::io::{Error, BufRead, BufReader, ErrorKind}; use random_string::generate; pub fn mount(tpath: &str, lpath: &str, hpath: &str, force: bool) -> Result<bool, Error> { if ! Path::new(&tpath).exists() { return Err(Error::new(ErrorKind::NotFound, format!("[{}] not found", &tpath))); } if Path::new(&lpath).exists() { if force { match remove_dir_all(&lpath) { Err(e) => return Err(e), _ => (), } } else { return Err(Error::new(ErrorKind::AlreadyExists, format!("[{}] already exists", &lpath))); } } let _hpath = format!("{}\\{}", lpath, hpath); mount_dir::mount(tpath, lpath, force)?; let app_data = format!("{}\\AppData", &_hpath); let roaming_app_data = format!("{}\\Roaming", &app_data); let local_app_data = format!("{}\\Local", &app_data); let temp = format!("{}\\Temp", &local_app_data); set_var("TMP", &temp); set_var("TEMP", &temp); set_var("HOME", &_hpath); set_var("HOMEPATH", &_hpath); set_var("USERPROFILE", &_hpath); set_var("HOMEDRIVE", get_disk(lpath)); set_var("APPDATA", &roaming_app_data); set_var("LOCALAPPDATA", &local_app_data); set_var("PORTABLE_DESKTOP_ENV_LINK_PATH", &lpath); set_var("PORTABLE_DESKTOP_ENV_TARGET_PATH", &tpath); let mut profile_path = format!("{}\\.profile.cmd", &_hpath); if ! Path::new(&profile_path).exists() { profile_path = format!("{}\\.profile.bat", &_hpath); } if Path::new(&profile_path).exists() { let env_flag = format!(".env.{}.tmp", generate(32, "1234567890")); let output = Command::new("cmd").args(["/C", &profile_path, "&", "echo", &env_flag, "&", "set"]).output().expect("process failed to execute"); let reader = BufReader::new(&*output.stdout); let mut is_env = false; for line in reader.lines() { let l = line.unwrap(); if ! is_env { if env_flag.eq(l.trim()) { is_env = true; } continue; } match l.trim().split_once('=') { Some((key, value)) => { set_var(key, value); } None => () } } } return Ok(true); } pub fn unmount(link: &str) -> bool { return mount_dir::unmount(link); } fn get_disk(path: &str) -> &str { match Path::new(path).components().next().unwrap() { Component::Prefix(prefix_component) => { return prefix_component.as_os_str().to_str().unwrap(); } _ => unreachable!(), } } #[cfg(test)] mod it_works { use super::*; use std::env; #[test] fn test_for_mount() { assert_eq!(mount(env::current_dir().unwrap().as_path().to_str().unwrap(), "T:\\work", "home", true).unwrap(), true); } #[test] fn test_for_unmount() { assert_eq!(unmount("T:\\work"), true); } }
解决方案
方法一:设置Windows进程创建标志隐藏窗口
在Windows平台下,可以通过给Command添加CREATE_NO_WINDOW标志禁止控制台窗口弹出,具体步骤如下:
- 添加依赖:在项目的
Cargo.toml中添加winapi依赖:
[dependencies] winapi = { version = "0.3", features = ["winbase"] }
- 导入常量:在Rust代码中导入所需的Windows API常量:
use winapi::um::winbase::CREATE_NO_WINDOW;
- 修改Command调用:在执行cmd的代码中添加
creation_flags配置:
let output = Command::new("cmd") .args(["/C", &profile_path, "&", "echo", &env_flag, "&", "set"]) .creation_flags(CREATE_NO_WINDOW) // 添加此行隐藏窗口 .output() .expect("process failed to execute");
方法二:使用PowerShell替代CMD(可选)
如果不想引入额外依赖,也可以改用PowerShell执行脚本,通过参数隐藏窗口:
let output = Command::new("powershell") .args(["-WindowStyle", "Hidden", "-Command", &format!("& '{}'; echo {}; set", profile_path, env_flag)]) .output() .expect("process failed to execute");
这种方式不需要额外依赖,但需要注意路径和命令的转义处理,避免空格或特殊字符导致执行错误。
内容的提问来源于stack exchange,提问作者Kerwin Bryant
相关产品推荐
相关产品推荐

