user_startup/utils/
windows.rs1use std::{
2 fs::File,
3 os::windows::process::CommandExt,
4 path::{Path, PathBuf},
5 process::Command,
6 sync::LazyLock as Lazy,
7};
8
9use super::parse_command;
10
11const CREATE_NO_WINDOW: u32 = 0x08000000;
12
13pub static CONFIG_PATH: Lazy<PathBuf> = Lazy::new(|| {
14 dirs::home_dir()
15 .expect("Could not find home directory")
16 .join("AppData")
17 .join("Roaming")
18 .join("Microsoft")
19 .join("Windows")
20 .join("Start Menu")
21 .join("Programs")
22 .join("Startup")
23});
24
25pub const COMMENT_PREFIX: &str = ":: ";
26
27pub fn comment(s: &str) -> String {
28 format!("{COMMENT_PREFIX}{s}")
29}
30
31pub const OPEN_COMMAND: &str = "explorer";
32
33pub const FILE_EXT: &str = ".cmd";
34
35fn escape_quotes(s: impl AsRef<str>) -> String {
36 s.as_ref().replace("\"", "^\"")
37}
38
39pub fn format(cmd: &str, _: Option<&str>, stdout: Option<&str>, stderr: Option<&str>) -> String {
40 format!(
41 r#"{prefixed_cmd}
42"{self_bin}" run "{cmd}" {stdout} {stderr}
43"#,
44 self_bin = std::env::current_exe()
45 .expect("Failed to get current executable path")
46 .display(),
47 prefixed_cmd = comment(cmd),
48 cmd = escape_quotes(cmd),
49 stdout = stdout.map_or(String::new(), |s| format!("--stdout {s}")),
50 stderr = stderr.map_or(String::new(), |s| format!("--stderr {s}"))
51 )
52}
53
54pub fn run_no_window(
56 cmd: impl AsRef<str>,
57 stdout: Option<impl AsRef<Path>>,
58 stderr: Option<impl AsRef<Path>>,
59) -> std::io::Result<()> {
60 let (bin, rest) = parse_command(cmd);
61 let mut command = Command::new(bin);
62 command.creation_flags(CREATE_NO_WINDOW).raw_arg(rest);
63 if let Some(stdout) = stdout {
64 let f = File::create(stdout)?;
65 command.stdout(f);
66 }
67 if let Some(stderr) = stderr {
68 let f = File::create(stderr)?;
69 command.stderr(f);
70 }
71 command.spawn()?;
72 Ok(())
73}