From b3e1c8a90770937350b0e825292bd1ede9acb861 Mon Sep 17 00:00:00 2001 From: fufesou <13586388+fufesou@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:49:48 +0800 Subject: [PATCH] Refact/msi more install options (#8949) * refact: msi, more install options Signed-off-by: fufesou * refact: msi, reg values on upgrade/modify Signed-off-by: fufesou * fix: msi, silent repair/upgrade, RemoveInstallFolder() Signed-off-by: fufesou * Options support both 1/0 and Y/N Signed-off-by: fufesou * refact: msi, preprocess, open file with explicit encoding Signed-off-by: fufesou * fix: msi, read previous options Signed-off-by: fufesou * fix: mis, install folder, read previous option Signed-off-by: fufesou * Comment on Control -> Checkbox Signed-off-by: fufesou * fix: UI, checkbox options, read previous values Signed-off-by: fufesou * fix: shortcuts options, init state Signed-off-by: fufesou * fix: shortcuts, init state Signed-off-by: fufesou * Better shortcuts property conditions Signed-off-by: fufesou --------- Signed-off-by: fufesou --- res/msi/CustomActions/CustomActions.cpp | 15 +++- res/msi/Package/Components/Folders.wxs | 20 ++++- res/msi/Package/Components/Regs.wxs | 12 +-- res/msi/Package/Components/RustDesk.wxs | 28 +++--- .../Package/Fragments/ShortcutProperties.wxs | 26 ++++-- res/msi/Package/Language/Package.en-us.wxl | 3 + res/msi/Package/Package.wxs | 11 ++- res/msi/Package/UI/AnotherApp.wxs | 2 +- res/msi/Package/UI/MyInstallDirDlg.wxs | 31 +++++++ res/msi/Package/UI/MyInstallDlg.wxs | 87 +++++++++++++++++++ res/msi/preprocess.py | 20 ++--- 11 files changed, 209 insertions(+), 46 deletions(-) create mode 100644 res/msi/Package/UI/MyInstallDirDlg.wxs create mode 100644 res/msi/Package/UI/MyInstallDlg.wxs diff --git a/res/msi/CustomActions/CustomActions.cpp b/res/msi/CustomActions/CustomActions.cpp index 91ba7e03c..afe06fdbb 100644 --- a/res/msi/CustomActions/CustomActions.cpp +++ b/res/msi/CustomActions/CustomActions.cpp @@ -31,6 +31,11 @@ LExit: return WcaFinalize(er); } +// CAUTION: We can't simply remove the install folder here, because silent repair/upgrade will fail. +// `RemoveInstallFolder()` is a deferred custom action, it will be executed after the files are copied. +// `msiexec /i package.msi /qn` +// +// So we need to delete the files separately in install folder. UINT __stdcall RemoveInstallFolder( __in MSIHANDLE hInstall) { @@ -41,6 +46,7 @@ UINT __stdcall RemoveInstallFolder( LPWSTR installFolder = NULL; LPWSTR pwz = NULL; LPWSTR pwzData = NULL; + WCHAR runtimeBroker[1024] = { 0, }; hr = WcaInitialize(hInstall, "RemoveInstallFolder"); ExitOnFailure(hr, "Failed to initialize"); @@ -52,21 +58,22 @@ UINT __stdcall RemoveInstallFolder( hr = WcaReadStringFromCaData(&pwz, &installFolder); ExitOnFailure(hr, "failed to read database key from custom action data: %ls", pwz); + StringCchPrintfW(runtimeBroker, sizeof(runtimeBroker) / sizeof(runtimeBroker[0]), L"%ls\\RuntimeBroker_rustdesk.exe", installFolder); + SHFILEOPSTRUCTW fileOp; ZeroMemory(&fileOp, sizeof(SHFILEOPSTRUCT)); - fileOp.wFunc = FO_DELETE; - fileOp.pFrom = installFolder; + fileOp.pFrom = runtimeBroker; fileOp.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; nResult = SHFileOperationW(&fileOp); if (nResult == 0) { - WcaLog(LOGMSG_STANDARD, "The directory \"%ls\" has been deleted.", installFolder); + WcaLog(LOGMSG_STANDARD, "The external file \"%ls\" has been deleted.", runtimeBroker); } else { - WcaLog(LOGMSG_STANDARD, "The directory \"%ls\" has not been deleted, error code: 0x%02X. Please refer to https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa for the error codes.", installFolder, nResult); + WcaLog(LOGMSG_STANDARD, "The external file \"%ls\" has not been deleted, error code: 0x%02X. Please refer to https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa for the error codes.", runtimeBroker, nResult); } LExit: diff --git a/res/msi/Package/Components/Folders.wxs b/res/msi/Package/Components/Folders.wxs index c39951019..de9edb7f3 100644 --- a/res/msi/Package/Components/Folders.wxs +++ b/res/msi/Package/Components/Folders.wxs @@ -3,8 +3,26 @@ + + + + + + + + + + + + + + + + - + diff --git a/res/msi/Package/Components/Regs.wxs b/res/msi/Package/Components/Regs.wxs index 23d4b6b8d..33d587b1e 100644 --- a/res/msi/Package/Components/Regs.wxs +++ b/res/msi/Package/Components/Regs.wxs @@ -5,16 +5,16 @@ - - + + - + - + @@ -22,7 +22,7 @@ - + @@ -36,7 +36,7 @@ - + diff --git a/res/msi/Package/Components/RustDesk.wxs b/res/msi/Package/Components/RustDesk.wxs index b2049f4e8..c17d60edb 100644 --- a/res/msi/Package/Components/RustDesk.wxs +++ b/res/msi/Package/Components/RustDesk.wxs @@ -4,7 +4,7 @@ - + @@ -12,10 +12,10 @@ - - - - + + + + @@ -29,7 +29,7 @@ - + @@ -88,8 +88,8 @@ - - + + - + diff --git a/res/msi/Package/Fragments/ShortcutProperties.wxs b/res/msi/Package/Fragments/ShortcutProperties.wxs index e800262fb..95bd4aaa3 100644 --- a/res/msi/Package/Fragments/ShortcutProperties.wxs +++ b/res/msi/Package/Fragments/ShortcutProperties.wxs @@ -25,11 +25,25 @@ - - + + - - + + + + + + + + + + + + + + + + @@ -45,8 +59,8 @@ - - + + diff --git a/res/msi/Package/Language/Package.en-us.wxl b/res/msi/Package/Language/Package.en-us.wxl index 517bde2af..1bd3986dd 100644 --- a/res/msi/Package/Language/Package.en-us.wxl +++ b/res/msi/Package/Language/Package.en-us.wxl @@ -49,4 +49,7 @@ This file contains the declaration of all the localizable strings. + + + diff --git a/res/msi/Package/Package.wxs b/res/msi/Package/Package.wxs index e86494e85..bdd8471cf 100644 --- a/res/msi/Package/Package.wxs +++ b/res/msi/Package/Package.wxs @@ -18,11 +18,11 @@ - + - + @@ -40,14 +40,17 @@ - + - + + + + diff --git a/res/msi/Package/UI/AnotherApp.wxs b/res/msi/Package/UI/AnotherApp.wxs index ea46812f7..168d1b10e 100644 --- a/res/msi/Package/UI/AnotherApp.wxs +++ b/res/msi/Package/UI/AnotherApp.wxs @@ -1,7 +1,7 @@ - + diff --git a/res/msi/Package/UI/MyInstallDirDlg.wxs b/res/msi/Package/UI/MyInstallDirDlg.wxs new file mode 100644 index 000000000..7c554a121 --- /dev/null +++ b/res/msi/Package/UI/MyInstallDirDlg.wxs @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/msi/Package/UI/MyInstallDlg.wxs b/res/msi/Package/UI/MyInstallDlg.wxs new file mode 100644 index 000000000..bf59d569c --- /dev/null +++ b/res/msi/Package/UI/MyInstallDlg.wxs @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/msi/preprocess.py b/res/msi/preprocess.py index a5251c1ce..9a43e9da6 100644 --- a/res/msi/preprocess.py +++ b/res/msi/preprocess.py @@ -90,7 +90,7 @@ def make_parser(): def read_lines_and_start_index(file_path, tag_start, tag_end): - with open(file_path, "r") as f: + with open(file_path, "r", encoding="utf-8") as f: lines = f.readlines() index_start = -1 index_end = -1 @@ -180,11 +180,11 @@ def gen_pre_vars(args, dist_dir): def replace_app_name_in_langs(app_name): langs_dir = Path(sys.argv[0]).parent.joinpath("Package/Language") for file_path in langs_dir.glob("*.wxl"): - with open(file_path, "r") as f: + with open(file_path, "r", encoding="utf-8") as f: lines = f.readlines() for i, line in enumerate(lines): lines[i] = line.replace("RustDesk", app_name) - with open(file_path, "w") as f: + with open(file_path, "w", encoding="utf-8") as f: f.writelines(lines) @@ -301,7 +301,7 @@ def gen_custom_ARPSYSTEMCOMPONENT_True(args, dist_dir): f'{indent}\n' ) lines_new.append( - f'{indent}\n' + f'{indent}\n' ) lines_new.append( f'{indent}\n' @@ -314,7 +314,7 @@ def gen_custom_ARPSYSTEMCOMPONENT_True(args, dist_dir): f'{indent}\n' ) lines_new.append( - f'{indent}\n' + f'{indent}\n' ) lines_new.append( f'{indent}\n' @@ -420,7 +420,7 @@ def gen_content_between_tags(filename, tag_start, tag_end, func): func(lines, index_start) - with open(target_file, "w") as f: + with open(target_file, "w", encoding="utf-8") as f: f.writelines(lines) return True @@ -480,19 +480,19 @@ def update_license_file(app_name): if app_name == "RustDesk": return license_file = Path(sys.argv[0]).parent.joinpath("Package/License.rtf") - with open(license_file, "r") as f: + with open(license_file, "r", encoding="utf-8") as f: license_content = f.read() license_content = license_content.replace("website rustdesk.com and other ", "") license_content = license_content.replace("RustDesk", app_name) license_content = re.sub("Purslane Ltd", app_name, license_content, flags=re.IGNORECASE) - with open(license_file, "w") as f: + with open(license_file, "w", encoding="utf-8") as f: f.write(license_content) def replace_component_guids_in_wxs(): langs_dir = Path(sys.argv[0]).parent.joinpath("Package") for file_path in langs_dir.glob("**/*.wxs"): - with open(file_path, "r") as f: + with open(file_path, "r", encoding="utf-8") as f: lines = f.readlines() # @@ -501,7 +501,7 @@ def replace_component_guids_in_wxs(): if match: lines[i] = re.sub(r'Guid="[^"]+"', f'Guid="{uuid.uuid4()}"', line) - with open(file_path, "w") as f: + with open(file_path, "w", encoding="utf-8") as f: f.writelines(lines)