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:
parent
049c334db3
commit
f4c40d733e
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
@ -73,6 +75,9 @@ class _InstallPageBodyState extends State<_InstallPageBody>
|
|||||||
|
|
||||||
_InstallPageBodyState() {
|
_InstallPageBodyState() {
|
||||||
controller = TextEditingController(text: bind.installInstallPath());
|
controller = TextEditingController(text: bind.installInstallPath());
|
||||||
|
final installOptions = jsonDecode(bind.installInstallOptions());
|
||||||
|
startmenu.value = installOptions['STARTMENUSHORTCUTS'] != '0';
|
||||||
|
desktopicon.value = installOptions['DESKTOPSHORTCUTS'] != '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -249,6 +254,7 @@ class _InstallPageBodyState extends State<_InstallPageBody>
|
|||||||
if (desktopicon.value) args += ' desktopicon';
|
if (desktopicon.value) args += ' desktopicon';
|
||||||
bind.installInstallMe(options: args, path: controller.text);
|
bind.installInstallMe(options: args, path: controller.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_install();
|
do_install();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
<Control Id="Folder" Type="PathEdit" X="20" Y="80" Width="320" Height="18" Property="WIXUI_INSTALLDIR" Indirect="yes" />
|
<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="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="140" Width="290" Height="17" Property="STARTMENUSHORTCUTS" CheckBoxValue="1" Text="!(loc.MyInstallDirDlgStartMenuShortcuts)" />
|
||||||
<Control Id="ChkBoxStartMenuShortcuts" Type="CheckBox" X="20" Y="160" 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>
|
</Dialog>
|
||||||
</UI>
|
</UI>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -1849,6 +1849,10 @@ pub fn install_install_path() -> SyncReturn<String> {
|
|||||||
SyncReturn(install_path())
|
SyncReturn(install_path())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn install_install_options() -> SyncReturn<String> {
|
||||||
|
SyncReturn(install_options())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_account_auth(op: String, remember_me: bool) {
|
pub fn main_account_auth(op: String, remember_me: bool) {
|
||||||
let id = get_id();
|
let id = get_id();
|
||||||
let uuid = get_uuid();
|
let uuid = get_uuid();
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
use super::{CursorData, ResultType};
|
use super::{CursorData, ResultType};
|
||||||
use crate::common::PORTABLE_APPNAME_RUNTIME_ENV_KEY;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
common::PORTABLE_APPNAME_RUNTIME_ENV_KEY,
|
||||||
custom_server::*,
|
custom_server::*,
|
||||||
ipc,
|
ipc,
|
||||||
privacy_mode::win_topmost_window::{self, WIN_TOPMOST_INJECTED_PROCESS_EXE},
|
privacy_mode::win_topmost_window::{self, WIN_TOPMOST_INJECTED_PROCESS_EXE},
|
||||||
};
|
};
|
||||||
use hbb_common::libc::{c_int, wchar_t};
|
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
anyhow::anyhow,
|
anyhow::anyhow,
|
||||||
bail,
|
bail,
|
||||||
config::{self, Config},
|
config::{self, Config},
|
||||||
|
libc::{c_int, wchar_t},
|
||||||
log,
|
log,
|
||||||
message_proto::{DisplayInfo, Resolution, WindowsSession},
|
message_proto::{DisplayInfo, Resolution, WindowsSession},
|
||||||
sleep, timeout, tokio,
|
sleep, timeout, tokio,
|
||||||
};
|
};
|
||||||
use std::process::{Command, Stdio};
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ffi::{CString, OsString},
|
ffi::{CString, OsString},
|
||||||
@ -24,15 +23,16 @@ use std::{
|
|||||||
mem,
|
mem,
|
||||||
os::windows::process::CommandExt,
|
os::windows::process::CommandExt,
|
||||||
path::*,
|
path::*,
|
||||||
|
process::{Command, Stdio},
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
sync::{atomic::Ordering, Arc, Mutex},
|
sync::{atomic::Ordering, Arc, Mutex},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use wallpaper;
|
use wallpaper;
|
||||||
use winapi::um::sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO};
|
|
||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::c_void,
|
ctypes::c_void,
|
||||||
shared::{minwindef::*, ntdef::NULL, windef::*, winerror::*},
|
shared::{minwindef::*, ntdef::NULL, windef::*, winerror::*},
|
||||||
|
um::sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO},
|
||||||
um::{
|
um::{
|
||||||
errhandlingapi::GetLastError,
|
errhandlingapi::GetLastError,
|
||||||
handleapi::CloseHandle,
|
handleapi::CloseHandle,
|
||||||
@ -63,13 +63,15 @@ use windows_service::{
|
|||||||
},
|
},
|
||||||
service_control_handler::{self, ServiceControlHandlerResult},
|
service_control_handler::{self, ServiceControlHandlerResult},
|
||||||
};
|
};
|
||||||
use winreg::enums::*;
|
use winreg::{enums::*, RegKey};
|
||||||
use winreg::RegKey;
|
|
||||||
|
|
||||||
pub const FLUTTER_RUNNER_WIN32_WINDOW_CLASS: &'static str = "FLUTTER_RUNNER_WIN32_WINDOW"; // main window, install window
|
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 EXPLORER_EXE: &'static str = "explorer.exe";
|
||||||
pub const SET_FOREGROUND_WINDOW: &'static str = "SET_FOREGROUND_WINDOW";
|
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> {
|
pub fn get_focused_display(displays: Vec<DisplayInfo>) -> Option<usize> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let hwnd = GetForegroundWindow();
|
let hwnd = GetForegroundWindow();
|
||||||
@ -992,6 +994,32 @@ fn get_valid_subkey() -> String {
|
|||||||
return get_subkey(&app_name, false);
|
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) {
|
pub fn get_install_info() -> (String, String, String, String) {
|
||||||
get_install_info_with_subkey(get_valid_subkey())
|
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 app_name = crate::get_app_name();
|
||||||
let ext = app_name.to_lowercase();
|
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))
|
hcu.delete_subkey_all(format!("Software\\Classes\\{}", exe))
|
||||||
.ok();
|
.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!("
|
format!("
|
||||||
chcp 65001
|
chcp 65001
|
||||||
reg add HKEY_CLASSES_ROOT\\.{ext} /f
|
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
|
||||||
reg add HKEY_CLASSES_ROOT\\.{ext}\\DefaultIcon /f /ve /t REG_SZ /d \"\\\"{exe}\\\",0\"
|
reg add HKEY_CLASSES_ROOT\\.{ext}\\DefaultIcon /f /ve /t REG_SZ /d \"\\\"{exe}\\\",0\"
|
||||||
reg add HKEY_CLASSES_ROOT\\.{ext}\\shell /f
|
reg add HKEY_CLASSES_ROOT\\.{ext}\\shell /f
|
||||||
@ -1197,6 +1244,8 @@ oLink.Save
|
|||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let tray_shortcut = get_tray_shortcut(&exe, &tmp_path)?;
|
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();
|
let mut shortcuts = Default::default();
|
||||||
if options.contains("desktopicon") {
|
if options.contains("desktopicon") {
|
||||||
shortcuts = format!(
|
shortcuts = format!(
|
||||||
@ -1204,6 +1253,7 @@ oLink.Save
|
|||||||
tmp_path,
|
tmp_path,
|
||||||
crate::get_app_name()
|
crate::get_app_name()
|
||||||
);
|
);
|
||||||
|
reg_value_desktop_shortcuts = "1".to_owned();
|
||||||
}
|
}
|
||||||
if options.contains("startmenu") {
|
if options.contains("startmenu") {
|
||||||
shortcuts = format!(
|
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}\\\"
|
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()?)?;
|
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("-", "."),
|
version = crate::VERSION.replace("-", "."),
|
||||||
build_date = crate::BUILD_DATE,
|
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 { "" },
|
sleep = if debug { "timeout 300" } else { "" },
|
||||||
dels = if debug { "" } else { &dels },
|
dels = if debug { "" } else { &dels },
|
||||||
copy_exe = copy_exe_cmd(&src_exe, &exe, &path)?,
|
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<()> {
|
pub fn run_after_install() -> ResultType<()> {
|
||||||
let (_, _, _, exe) = get_install_info();
|
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<()> {
|
pub fn run_before_uninstall() -> ResultType<()> {
|
||||||
|
@ -312,6 +312,10 @@ impl UI {
|
|||||||
install_path()
|
install_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn install_options(&self) -> String {
|
||||||
|
install_options()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_socks(&self) -> Value {
|
fn get_socks(&self) -> Value {
|
||||||
Value::from_iter(get_socks())
|
Value::from_iter(get_socks())
|
||||||
}
|
}
|
||||||
@ -683,6 +687,7 @@ impl sciter::EventHandler for UI {
|
|||||||
fn set_share_rdp(bool);
|
fn set_share_rdp(bool);
|
||||||
fn is_installed_lower_version();
|
fn is_installed_lower_version();
|
||||||
fn install_path();
|
fn install_path();
|
||||||
|
fn install_options();
|
||||||
fn goto_install();
|
fn goto_install();
|
||||||
fn is_process_trusted(bool);
|
fn is_process_trusted(bool);
|
||||||
fn is_can_screen_recording(bool);
|
fn is_can_screen_recording(bool);
|
||||||
|
@ -6,13 +6,16 @@ var install_path = "";
|
|||||||
|
|
||||||
class Install: Reactor.Component {
|
class Install: Reactor.Component {
|
||||||
function render() {
|
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>
|
return <div .content>
|
||||||
<div style="font-size: 2em;">{translate('Installation')}</div>
|
<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 />
|
<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>
|
<button .button .outline #path style="margin-left: 1em">{translate('Change Path')}</button>
|
||||||
</div>
|
</div>
|
||||||
<div><button|checkbox #startmenu checked>{translate('Create start menu shortcuts')}</button></div>
|
<div><button|checkbox #startmenu {startmenu_shortcuts}>{translate('Create start menu shortcuts')}</button></div>
|
||||||
<div><button|checkbox #desktopicon checked>{translate('Create desktop icon')}</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 #agreement .link style="margin-top: 2em;">{translate('End-user license agreement')}</div>
|
||||||
<div>{translate('agreement_tip')}</div>
|
<div>{translate('agreement_tip')}</div>
|
||||||
<div style="height: 1px; background: gray; margin-top: 1em" />
|
<div style="height: 1px; background: gray; margin-top: 1em" />
|
||||||
|
@ -426,6 +426,14 @@ pub fn install_path() -> String {
|
|||||||
return "".to_owned();
|
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]
|
#[inline]
|
||||||
pub fn get_socks() -> Vec<String> {
|
pub fn get_socks() -> Vec<String> {
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user