mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Relocates Update.exe to writable location
Moves the Update.exe file to the local app data directory if the application directory is not writable. This ensures that the application can update itself even when installed in a protected location like Program Files. Adds anyhow dependency to rust library.
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2342,6 +2342,7 @@ checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5"
|
||||
name = "velopack"
|
||||
version = "0.0.0-local"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-std",
|
||||
"bitflags 2.9.1",
|
||||
"derivative",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Versioning;
|
||||
@@ -119,12 +118,11 @@ namespace Velopack.Locators
|
||||
|
||||
if (UpdateExePath != null
|
||||
&& Path.GetDirectoryName(UpdateExePath) is { } updateExeDirectory
|
||||
&& !PathUtil.IsDirectoryWritable(updateExeDirectory)) {
|
||||
var tempTargetUpdateExe = Path.Combine(TempAppRootDirectory, "Update.exe");
|
||||
&& !PathUtil.IsDirectoryWritable(updateExeDirectory) &&
|
||||
PackagesDir is { } packagesDir) {
|
||||
var tempTargetUpdateExe = Path.Combine(packagesDir, "Update.exe");
|
||||
if (File.Exists(UpdateExePath) && !File.Exists(tempTargetUpdateExe)) {
|
||||
initLog.Warn("Application directory is not writable. Copying Update.exe to temp location: " + tempTargetUpdateExe);
|
||||
// Debugger.Launch();
|
||||
Directory.CreateDirectory(TempAppRootDirectory);
|
||||
File.Copy(UpdateExePath, tempTargetUpdateExe);
|
||||
}
|
||||
|
||||
@@ -165,7 +163,7 @@ namespace Velopack.Locators
|
||||
initLog.Trace($"File logger exception: {fileLogException}");
|
||||
}
|
||||
|
||||
if (AppId == null) {
|
||||
if (AppId is null) {
|
||||
initLog.Warn(
|
||||
$"Failed to initialize {nameof(WindowsVelopackLocator)}. This could be because the program is not installed or packaged properly.");
|
||||
} else {
|
||||
@@ -180,7 +178,7 @@ namespace Velopack.Locators
|
||||
string? writableRootDir = PossibleDirectories()
|
||||
.FirstOrDefault(IsWritable);
|
||||
|
||||
if (writableRootDir == null) {
|
||||
if (writableRootDir is null) {
|
||||
Log.Warn("Unable to find a writable root directory for package.");
|
||||
return null;
|
||||
}
|
||||
@@ -191,7 +189,7 @@ namespace Velopack.Locators
|
||||
|
||||
static bool IsWritable(string? directoryPath)
|
||||
{
|
||||
if (directoryPath == null) return false;
|
||||
if (directoryPath is null) return false;
|
||||
|
||||
try {
|
||||
if (!Directory.Exists(directoryPath)) {
|
||||
@@ -206,11 +204,11 @@ namespace Velopack.Locators
|
||||
|
||||
IEnumerable<string?> PossibleDirectories()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(AppId)) {
|
||||
yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "velopack", AppId);
|
||||
}
|
||||
yield return RootAppDir;
|
||||
yield return TempAppRootDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
private string TempAppRootDirectory => Path.Combine(Path.GetTempPath(), "velopack_" + AppId);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ tempfile.workspace = true
|
||||
|
||||
[dependencies]
|
||||
log.workspace = true
|
||||
anyhow.workspace = true
|
||||
ureq.workspace = true
|
||||
url.workspace = true
|
||||
semver.workspace = true
|
||||
|
||||
32
src/lib-rust/src/known_path.rs
Normal file
32
src/lib-rust/src/known_path.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use anyhow::{bail, Result};
|
||||
use std::path::PathBuf;
|
||||
use crate::wide_strings::wide_to_os_string;
|
||||
use windows::{
|
||||
core::GUID,
|
||||
Win32::UI::Shell::{
|
||||
FOLDERID_LocalAppData, SHGetKnownFolderPath
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
fn get_known_folder(rfid: *const GUID) -> Result<PathBuf> {
|
||||
unsafe {
|
||||
let flag = windows::Win32::UI::Shell::KNOWN_FOLDER_FLAG(0);
|
||||
let result = SHGetKnownFolderPath(rfid, flag, None)?;
|
||||
if result.is_null() {
|
||||
bail!("Failed to get known folder path (SHGetKnownFolderPath returned null)");
|
||||
}
|
||||
|
||||
let str = wide_to_os_string(result);
|
||||
let path = PathBuf::from(str);
|
||||
Ok(path)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn get_local_app_data() -> Result<PathBuf> {
|
||||
get_known_folder(&FOLDERID_LocalAppData)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -134,8 +134,7 @@ pub mod locator;
|
||||
pub mod sources;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
maybe_pub!(wide_strings);
|
||||
|
||||
maybe_pub!(known_path, wide_strings);
|
||||
maybe_pub!(download, bundle, constants, lockfile, logging, misc);
|
||||
maybe_pub_os!(process, "process_win.rs", "process_unix.rs");
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@ use semver::Version;
|
||||
use std::path::PathBuf;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(windows)]
|
||||
use crate:: {
|
||||
known_path::get_local_app_data
|
||||
};
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
/// ShortcutLocationFlags is a bitflags enumeration of system shortcut locations.
|
||||
@@ -124,13 +129,13 @@ impl VelopackLocator {
|
||||
pub fn new_with_manifest(mut paths: VelopackLocatorConfig, manifest: Manifest) -> Self {
|
||||
let root = paths.RootAppDir.clone();
|
||||
if root.starts_with("C:\\Program Files") || !misc::is_directory_writable(&root) {
|
||||
let temp_root = std::env::temp_dir().join(format!("velopack_{}", manifest.id));
|
||||
let velopack_package_root = get_local_app_data().unwrap().join("velopack").join(&manifest.id);
|
||||
let orig_update_path = paths.UpdateExePath.clone();
|
||||
paths.PackagesDir = temp_root.join("packages");
|
||||
paths.PackagesDir = velopack_package_root.join("packages");
|
||||
if !paths.PackagesDir.exists() {
|
||||
std::fs::create_dir_all(&paths.PackagesDir).unwrap();
|
||||
}
|
||||
paths.UpdateExePath = temp_root.join("Update.exe");
|
||||
paths.UpdateExePath = velopack_package_root.join("Update.exe");
|
||||
if !paths.UpdateExePath.exists() && orig_update_path.exists() {
|
||||
std::fs::copy(orig_update_path, &paths.UpdateExePath).unwrap();
|
||||
warn!("Application directory is not writable. Copying Update.exe to temp location: {:?}", paths.UpdateExePath);
|
||||
|
||||
Reference in New Issue
Block a user