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