Create desktop shortcut by default

This commit is contained in:
Caelan Sayler
2024-01-12 11:43:22 +00:00
parent 76ccf42267
commit 383c9aca4f
4 changed files with 58 additions and 25 deletions

View File

@@ -168,12 +168,8 @@ fn install_impl(pkg: &bundle::BundleInfo, root_path: &PathBuf, tx: &std::sync::m
bail!("The main executable could not be found in the package. Please contact the application author.");
}
info!("Creating start menu shortcut...");
let startmenu = w::SHGetKnownFolderPath(&co::KNOWNFOLDERID::StartMenu, co::KF::DONT_UNEXPAND, None)?;
let lnk_path = Path::new(&startmenu).join("Programs").join(format!("{}.lnk", &app.title));
if let Err(e) = windows::create_lnk(&lnk_path.to_string_lossy(), &main_exe_path, &current_path, None) {
warn!("Failed to create start menu shortcut: {}", e);
}
info!("Creating new default shortcuts...");
let _ = windows::create_default_lnks(&root_path, &app);
let ver_string = app.version.to_string();
info!("Starting process install hook: \"{}\" --veloapp-install {}", &main_exe_path, &ver_string);

View File

@@ -8,7 +8,6 @@ use std::{
fs,
path::{Path, PathBuf},
};
use winsafe::{self as w, co};
pub fn start(wait_for_parent: bool, exe_name: Option<&String>, exe_args: Option<Vec<&str>>, legacy_args: Option<&String>) -> Result<()> {
if legacy_args.is_some() && exe_args.is_some() {
@@ -86,7 +85,6 @@ fn try_legacy_migration(root_dir: &PathBuf, app: &bundle::Manifest) -> Result<()
warn!("This application is installed in a folder prefixed with 'app-'. Attempting to migrate...");
let _ = shared::force_stop_package(&root_dir);
let current_dir = app.get_current_path(&root_dir);
let main_exe_path = app.get_main_exe_path(&root_dir);
if !Path::new(&current_dir).exists() {
info!("Renaming latest app-* folder to current.");
@@ -108,12 +106,8 @@ fn try_legacy_migration(root_dir: &PathBuf, app: &bundle::Manifest) -> Result<()
warn!("Failed to remove shortcuts ({}).", e);
}
info!("Creating start menu shortcut...");
let startmenu = w::SHGetKnownFolderPath(&co::KNOWNFOLDERID::StartMenu, co::KF::DONT_UNEXPAND, None)?;
let lnk_path = Path::new(&startmenu).join("Programs").join(format!("{}.lnk", &app.title));
if let Err(e) = windows::create_lnk(&lnk_path.to_string_lossy(), &main_exe_path, &current_dir, None) {
warn!("Failed to create start menu shortcut: {}", e);
}
info!("Creating new default shortcuts...");
let _ = windows::create_default_lnks(&root_dir, &app);
Ok(())
}

View File

@@ -1,11 +1,12 @@
use crate::bundle::Manifest;
use crate::shared as util;
use anyhow::Result;
use anyhow::{bail, Result};
use glob::glob;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::time::Duration;
use winsafe::{self as w, co};
use windows::core::{ComInterface, Result as WindowsResult, GUID, PCWSTR, HSTRING, IntoParam, Param};
use windows::core::{ComInterface, IntoParam, Param, Result as WindowsResult, GUID, HSTRING, PCWSTR};
use windows::Win32::Foundation::HWND;
use windows::Win32::Storage::EnhancedStorage::PKEY_AppUserModel_ID;
use windows::Win32::System::Com::StructuredStorage::InitPropVariantFromStringVector;
@@ -27,7 +28,43 @@ fn create_instance<T: ComInterface>(clsid: &GUID) -> WindowsResult<T> {
unsafe { CoCreateInstance(clsid, None, CLSCTX_ALL) }
}
pub fn create_lnk(output: &str, target: &str, work_dir: &str, app_model_id: Option<&str>) -> WindowsResult<()> {
pub fn create_default_lnks(root_path: &PathBuf, app: &Manifest) -> Result<()> {
let app = app.clone();
let current_path = app.get_current_path(root_path);
let main_exe_path = app.get_main_exe_path(root_path);
let t = std::thread::spawn(move || {
init_com()?;
let mut was_error = false;
info!("Creating desktop shortcut...");
let desktop = w::SHGetKnownFolderPath(&co::KNOWNFOLDERID::Desktop, co::KF::DONT_UNEXPAND, None)?;
let desktop_lnk = Path::new(&desktop).join(format!("{}.lnk", &app.title));
if let Err(e) = _create_lnk(&desktop_lnk.to_string_lossy(), &main_exe_path, &current_path, None) {
warn!("Failed to create start menu shortcut: {}", e);
was_error = true;
}
std::thread::sleep(Duration::from_millis(1));
info!("Creating start menu shortcut...");
let startmenu = w::SHGetKnownFolderPath(&co::KNOWNFOLDERID::StartMenu, co::KF::DONT_UNEXPAND, None)?;
let start_lnk = Path::new(&startmenu).join("Programs").join(format!("{}.lnk", &app.title));
if let Err(e) = _create_lnk(&start_lnk.to_string_lossy(), &main_exe_path, &current_path, None) {
warn!("Failed to create start menu shortcut: {}", e);
was_error = true;
}
if was_error {
bail!("Failed to create one or both default shortcuts");
}
Ok(())
});
t.join().unwrap()
}
#[allow(dead_code)]
fn create_lnk(output: &str, target: &str, work_dir: &str, app_model_id: Option<&str>) -> WindowsResult<()> {
let output = output.to_string();
let target = target.to_string();
let work_dir = work_dir.to_string();

View File

@@ -303,13 +303,18 @@ public class WindowsPackTests
var argsContent = File.ReadAllText(argsPath).Trim();
Assert.Equal("--veloapp-install 1.0.0", argsContent);
var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs", id + ".lnk");
Assert.True(File.Exists(shortcutPath));
void CheckShortcut(string path)
{
Assert.True(File.Exists(path));
var lnk = new ShellLink(path);
Assert.Equal(Path.Combine(tmpInstallDir, "current"), lnk.WorkingDirectory);
Assert.Equal(appPath, lnk.Target);
}
var lnk = new ShellLink(shortcutPath);
var currentPath = Path.Combine(tmpInstallDir, "current");
Assert.Equal(currentPath, lnk.WorkingDirectory);
Assert.Equal(appPath, lnk.Target);
var startLnk = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs", id + ".lnk");
var desktopLnk = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), id + ".lnk");
CheckShortcut(startLnk);
CheckShortcut(desktopLnk);
// check registry exists
string installDate = null;
@@ -325,7 +330,8 @@ public class WindowsPackTests
var uninstOutput = RunNoCoverage(updatePath, new string[] { "--nocolor", "--silent", "--uninstall" }, Environment.CurrentDirectory, logger);
Assert.EndsWith(Environment.NewLine + "Y", uninstOutput); // this checks that the self-delete succeeded
Assert.False(File.Exists(shortcutPath));
Assert.False(File.Exists(startLnk));
Assert.False(File.Exists(desktopLnk));
Assert.False(File.Exists(appPath));
using (var key2 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default)