use std::path::PathBuf;
use std::process::Command;
use crate::platform::autostart::{AutostartError, AutostartProgram};
pub fn render_registration(program: &AutostartProgram<'_>) -> String {
let binary = program.program.to_string_lossy();
let run = cmd_quote(&format!("{binary} {}", program.start_argument));
format!(
"schtasks /Create /SC ONLOGON /TN {task} /TR {run} /RL HIGHEST /F",
task = cmd_quote(program.identifier),
)
}
pub fn register(program: &AutostartProgram<'_>) -> Result<PathBuf, AutostartError> {
let binary = program.program.to_string_lossy().into_owned();
let run = format!("{binary} {}", program.start_argument);
let status = Command::new("schtasks")
.args([
"/Create",
"/SC",
"ONLOGON",
"/TN",
program.identifier,
"/TR",
&run,
"/RL",
"HIGHEST",
"/F",
])
.status()
.map_err(|error| AutostartError::InitSystem(format!("schtasks /Create failed: {error}")))?;
if !status.success() {
return Err(AutostartError::InitSystem(format!(
"schtasks /Create exited non-zero ({status})"
)));
}
Ok(task_location(program))
}
pub fn unregister(program: &AutostartProgram<'_>) -> Result<(), AutostartError> {
let status = Command::new("schtasks")
.args(["/Delete", "/TN", program.identifier, "/F"])
.status()
.map_err(|error| AutostartError::InitSystem(format!("schtasks /Delete failed: {error}")))?;
if !status.success() {
eprintln!("warning: schtasks /Delete returned non-zero ({status:?}) (already removed?)");
}
Ok(())
}
fn task_location(program: &AutostartProgram<'_>) -> PathBuf {
PathBuf::from(format!(r"\Task Scheduler\{}", program.identifier))
}
fn cmd_quote(value: &str) -> String {
let escaped = value.replace('"', "\"\"");
format!("\"{escaped}\"")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cmd_quote_doubles_embedded_quotes() {
assert_eq!(
cmd_quote(r#"C:\path with "quotes"\runpm.exe"#),
"\"C:\\path with \"\"quotes\"\"\\runpm.exe\""
);
}
}