Fix/exe upgrade options (#9001)

* fix: exe upgrade, use previous options

Signed-off-by: fufesou <linlong1266@gmail.com>

* refact: msi, shortcuts options, swap pos

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2024-08-08 22:07:06 +08:00 committed by GitHub
parent 049c334db3
commit f4c40d733e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 94 additions and 13 deletions

View File

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';
@ -73,6 +75,9 @@ class _InstallPageBodyState extends State<_InstallPageBody>
_InstallPageBodyState() {
controller = TextEditingController(text: bind.installInstallPath());
final installOptions = jsonDecode(bind.installInstallOptions());
startmenu.value = installOptions['STARTMENUSHORTCUTS'] != '0';
desktopicon.value = installOptions['DESKTOPSHORTCUTS'] != '0';
}
@override
@ -249,6 +254,7 @@ class _InstallPageBodyState extends State<_InstallPageBody>
if (desktopicon.value) args += ' desktopicon';
bind.installInstallMe(options: args, path: controller.text);
}
do_install();
}

View File

@ -23,8 +23,8 @@
<Control Id="Folder" Type="PathEdit" X="20" Y="80" Width="320" Height="18" Property="WIXUI_INSTALLDIR" Indirect="yes" />
<Control Id="ChangeFolder" Type="PushButton" X="20" Y="100" Width="56" Height="17" Text="!(loc.InstallDirDlgChange)" />
<Control Id="ChkBoxDesktopShortcuts" Type="CheckBox" X="20" Y="140" Width="290" Height="17" Property="DESKTOPSHORTCUTS" CheckBoxValue="1" Text="!(loc.MyInstallDirDlgDesktopShortcuts)" />
<Control Id="ChkBoxStartMenuShortcuts" Type="CheckBox" X="20" Y="160" Width="290" Height="17" Property="STARTMENUSHORTCUTS" CheckBoxValue="1" Text="!(loc.MyInstallDirDlgStartMenuShortcuts)" />
<Control Id="ChkBoxStartMenuShortcuts" Type="CheckBox" X="20" Y="140" Width="290" Height="17" Property="STARTMENUSHORTCUTS" CheckBoxValue="1" Text="!(loc.MyInstallDirDlgStartMenuShortcuts)" />
<Control Id="ChkBoxDesktopShortcuts" Type="CheckBox" X="20" Y="160" Width="290" Height="17" Property="DESKTOPSHORTCUTS" CheckBoxValue="1" Text="!(loc.MyInstallDirDlgDesktopShortcuts)" />
</Dialog>
</UI>
</Fragment>

View File

@ -1849,6 +1849,10 @@ pub fn install_install_path() -> SyncReturn<String> {
SyncReturn(install_path())
}
pub fn install_install_options() -> SyncReturn<String> {
SyncReturn(install_options())
}
pub fn main_account_auth(op: String, remember_me: bool) {
let id = get_id();
let uuid = get_uuid();

View File

@ -1,21 +1,20 @@
use super::{CursorData, ResultType};
use crate::common::PORTABLE_APPNAME_RUNTIME_ENV_KEY;
use crate::{
common::PORTABLE_APPNAME_RUNTIME_ENV_KEY,
custom_server::*,
ipc,
privacy_mode::win_topmost_window::{self, WIN_TOPMOST_INJECTED_PROCESS_EXE},
};
use hbb_common::libc::{c_int, wchar_t};
use hbb_common::{
allow_err,
anyhow::anyhow,
bail,
config::{self, Config},
libc::{c_int, wchar_t},
log,
message_proto::{DisplayInfo, Resolution, WindowsSession},
sleep, timeout, tokio,
};
use std::process::{Command, Stdio};
use std::{
collections::HashMap,
ffi::{CString, OsString},
@ -24,15 +23,16 @@ use std::{
mem,
os::windows::process::CommandExt,
path::*,
process::{Command, Stdio},
ptr::null_mut,
sync::{atomic::Ordering, Arc, Mutex},
time::{Duration, Instant},
};
use wallpaper;
use winapi::um::sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO};
use winapi::{
ctypes::c_void,
shared::{minwindef::*, ntdef::NULL, windef::*, winerror::*},
um::sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO},
um::{
errhandlingapi::GetLastError,
handleapi::CloseHandle,
@ -63,13 +63,15 @@ use windows_service::{
},
service_control_handler::{self, ServiceControlHandlerResult},
};
use winreg::enums::*;
use winreg::RegKey;
use winreg::{enums::*, RegKey};
pub const FLUTTER_RUNNER_WIN32_WINDOW_CLASS: &'static str = "FLUTTER_RUNNER_WIN32_WINDOW"; // main window, install window
pub const EXPLORER_EXE: &'static str = "explorer.exe";
pub const SET_FOREGROUND_WINDOW: &'static str = "SET_FOREGROUND_WINDOW";
const REG_NAME_INSTALL_DESKTOPSHORTCUTS: &str = "DESKTOPSHORTCUTS";
const REG_NAME_INSTALL_STARTMENUSHORTCUTS: &str = "STARTMENUSHORTCUTS";
pub fn get_focused_display(displays: Vec<DisplayInfo>) -> Option<usize> {
unsafe {
let hwnd = GetForegroundWindow();
@ -992,6 +994,32 @@ fn get_valid_subkey() -> String {
return get_subkey(&app_name, false);
}
// Return install options other than InstallLocation.
pub fn get_install_options() -> String {
let app_name = crate::get_app_name();
let subkey = format!(".{}", app_name.to_lowercase());
let mut opts = HashMap::new();
let desktop_shortcuts = get_reg_of_hkcr(&subkey, REG_NAME_INSTALL_DESKTOPSHORTCUTS);
if let Some(desktop_shortcuts) = desktop_shortcuts {
opts.insert(REG_NAME_INSTALL_DESKTOPSHORTCUTS, desktop_shortcuts);
}
let start_menu_shortcuts = get_reg_of_hkcr(&subkey, REG_NAME_INSTALL_STARTMENUSHORTCUTS);
if let Some(start_menu_shortcuts) = start_menu_shortcuts {
opts.insert(REG_NAME_INSTALL_STARTMENUSHORTCUTS, start_menu_shortcuts);
}
serde_json::to_string(&opts).unwrap_or("{}".to_owned())
}
// This function return Option<String>, because some registry value may be empty.
fn get_reg_of_hkcr(subkey: &str, name: &str) -> Option<String> {
let hkcr = RegKey::predef(HKEY_CLASSES_ROOT);
if let Ok(tmp) = hkcr.open_subkey(subkey.replace("HKEY_CLASSES_ROOT\\", "")) {
return tmp.get_value(name).ok();
}
None
}
pub fn get_install_info() -> (String, String, String, String) {
get_install_info_with_subkey(get_valid_subkey())
}
@ -1101,7 +1129,11 @@ pub fn copy_exe_cmd(src_exe: &str, exe: &str, path: &str) -> ResultType<String>
))
}
fn get_after_install(exe: &str) -> String {
fn get_after_install(
exe: &str,
reg_value_start_menu_shortcuts: Option<String>,
reg_value_desktop_shortcuts: Option<String>,
) -> String {
let app_name = crate::get_app_name();
let ext = app_name.to_lowercase();
@ -1112,9 +1144,24 @@ fn get_after_install(exe: &str) -> String {
hcu.delete_subkey_all(format!("Software\\Classes\\{}", exe))
.ok();
let desktop_shortcuts = reg_value_desktop_shortcuts
.map(|v| {
format!("reg add HKEY_CLASSES_ROOT\\.{ext} /f /v {REG_NAME_INSTALL_DESKTOPSHORTCUTS} /t REG_SZ /d \"{v}\"")
})
.unwrap_or_default();
let start_menu_shortcuts = reg_value_start_menu_shortcuts
.map(|v| {
format!(
"reg add HKEY_CLASSES_ROOT\\.{ext} /f /v {REG_NAME_INSTALL_STARTMENUSHORTCUTS} /t REG_SZ /d \"{v}\""
)
})
.unwrap_or_default();
format!("
chcp 65001
reg add HKEY_CLASSES_ROOT\\.{ext} /f
{desktop_shortcuts}
{start_menu_shortcuts}
reg add HKEY_CLASSES_ROOT\\.{ext}\\DefaultIcon /f
reg add HKEY_CLASSES_ROOT\\.{ext}\\DefaultIcon /f /ve /t REG_SZ /d \"\\\"{exe}\\\",0\"
reg add HKEY_CLASSES_ROOT\\.{ext}\\shell /f
@ -1197,6 +1244,8 @@ oLink.Save
.unwrap_or("")
.to_owned();
let tray_shortcut = get_tray_shortcut(&exe, &tmp_path)?;
let mut reg_value_desktop_shortcuts = "0".to_owned();
let mut reg_value_start_menu_shortcuts = "0".to_owned();
let mut shortcuts = Default::default();
if options.contains("desktopicon") {
shortcuts = format!(
@ -1204,6 +1253,7 @@ oLink.Save
tmp_path,
crate::get_app_name()
);
reg_value_desktop_shortcuts = "1".to_owned();
}
if options.contains("startmenu") {
shortcuts = format!(
@ -1213,6 +1263,7 @@ copy /Y \"{tmp_path}\\{app_name}.lnk\" \"{start_menu}\\\"
copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{start_menu}\\\"
"
);
reg_value_start_menu_shortcuts = "1".to_owned();
}
let meta = std::fs::symlink_metadata(std::env::current_exe()?)?;
@ -1281,7 +1332,11 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\"
",
version = crate::VERSION.replace("-", "."),
build_date = crate::BUILD_DATE,
after_install = get_after_install(&exe),
after_install = get_after_install(
&exe,
Some(reg_value_start_menu_shortcuts),
Some(reg_value_desktop_shortcuts)
),
sleep = if debug { "timeout 300" } else { "" },
dels = if debug { "" } else { &dels },
copy_exe = copy_exe_cmd(&src_exe, &exe, &path)?,
@ -1294,7 +1349,7 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\"
pub fn run_after_install() -> ResultType<()> {
let (_, _, _, exe) = get_install_info();
run_cmds(get_after_install(&exe), true, "after_install")
run_cmds(get_after_install(&exe, None, None), true, "after_install")
}
pub fn run_before_uninstall() -> ResultType<()> {

View File

@ -312,6 +312,10 @@ impl UI {
install_path()
}
fn install_options(&self) -> String {
install_options()
}
fn get_socks(&self) -> Value {
Value::from_iter(get_socks())
}
@ -683,6 +687,7 @@ impl sciter::EventHandler for UI {
fn set_share_rdp(bool);
fn is_installed_lower_version();
fn install_path();
fn install_options();
fn goto_install();
fn is_process_trusted(bool);
fn is_can_screen_recording(bool);

View File

@ -6,13 +6,16 @@ var install_path = "";
class Install: Reactor.Component {
function render() {
const install_options = JSON.parse(view.install_options());
const desktop_icon = { checked: install_options?.DESKTOPSHORTCUTS == '0' ? false : true };
const startmenu_shortcuts = { checked: install_options?.STARTMENUSHORTCUTS == '0' ? false : true };
return <div .content>
<div style="font-size: 2em;">{translate('Installation')}</div>
<div style="margin: 2em 0;">{translate('Installation Path')} {": "}<input|text disabled value={view.install_path()} #path_input />
<button .button .outline #path style="margin-left: 1em">{translate('Change Path')}</button>
</div>
<div><button|checkbox #startmenu checked>{translate('Create start menu shortcuts')}</button></div>
<div><button|checkbox #desktopicon checked>{translate('Create desktop icon')}</button></div>
<div><button|checkbox #startmenu {startmenu_shortcuts}>{translate('Create start menu shortcuts')}</button></div>
<div><button|checkbox #desktopicon {desktop_icon}>{translate('Create desktop icon')}</button></div>
<div #agreement .link style="margin-top: 2em;">{translate('End-user license agreement')}</div>
<div>{translate('agreement_tip')}</div>
<div style="height: 1px; background: gray; margin-top: 1em" />

View File

@ -426,6 +426,14 @@ pub fn install_path() -> String {
return "".to_owned();
}
#[inline]
pub fn install_options() -> String {
#[cfg(windows)]
return crate::platform::windows::get_install_options();
#[cfg(not(windows))]
return "{}".to_owned();
}
#[inline]
pub fn get_socks() -> Vec<String> {
#[cfg(not(any(target_os = "android", target_os = "ios")))]