diff --git a/src/install.rs b/src/install.rs index 88e721c..1a4ee5b 100644 --- a/src/install.rs +++ b/src/install.rs @@ -189,13 +189,48 @@ impl<'a> Step<'a> { ensure!(status.success(), EXECUTE_COMMAND_ERROR_MSG); } Self::CreateShortcut { target, icon, file } => { + const CREATE_SHORTCUT_ERROR_MSG: &'static str = "Creating shortcut failed."; mkdir_all( file.parent().ok_or_else(|| { miette!("Destination file for shortcut step has no parent.") })?, ) .await?; - todo!(); + let status = match target { + ShortcutTarget::Path { path } => { + tokio::process::Command::new("powershell") + .arg("-Command") + .arg(format!(r#"$shell = New-Object -ComObject WScript.Shell; $shortcut = $shell.CreateShortcut({file:?}); $shortcut.TargetPath = {path:?}; $shortcut.Save()"#)) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .status() + .await + .into_diagnostic() + .wrap_err(CREATE_SHORTCUT_ERROR_MSG)? + } + ShortcutTarget::Executable { file: exec_file, args } => { + use std::fmt::Write; + let mut args_str = String::new(); + let mut args = args.into_iter(); + if let Some(arg) = args.next() { + // TODO: quote properly + write!(args_str, "{:?}", arg).unwrap(); + } + for arg in args { + write!(args_str, " {:?}", arg).unwrap(); + } + tokio::process::Command::new("powershell") + .arg("-Command") + .arg(format!(r#"$shell = New-Object -ComObject WScript.Shell; $shortcut = $shell.CreateShortcut({file:?}); $shortcut.TargetPath = {exec_file:?}; $shortcut.Arguments = {args_str:?}; $shortcut.Save()"#)) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .status() + .await + .into_diagnostic() + .wrap_err(CREATE_SHORTCUT_ERROR_MSG)? + } + }; + ensure!(status.success(), CREATE_SHORTCUT_ERROR_MSG); } } println!("-> Done."); @@ -230,7 +265,7 @@ pub enum ShortcutTarget<'a> { file: Cow<'a, Path>, /// Arguments to the executable. - arg: &'a [&'a str], + args: &'a [&'a str], }, /// A file or folder shortcut. Please use [`Self::Executable`] for shortcuts to binaries.