From f673647072dd321ffdcb5956c029a1b6f867cd4a Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 11 Apr 2024 18:54:32 +0800 Subject: [PATCH] Feat/msi (#7688) * Feat. Msi, check is self-installed Signed-off-by: fufesou * Feat. Msi. 1. Check if is self-installation. 2. Add firewall rule by custom action. Signed-off-by: fufesou * Feat. Msi, github ci Signed-off-by: fufesou * Feat. Msi, github ci Signed-off-by: fufesou * Feat. Msi, github ci Signed-off-by: fufesou * Feat. Msi, refact preprocess.py Signed-off-by: fufesou * Feat. Msi Signed-off-by: fufesou * Trivial, renames Signed-off-by: fufesou --------- Signed-off-by: fufesou --- .github/workflows/flutter-build.yml | 13 + res/msi/CustomActions/CustomActions.cpp | 117 +++++ res/msi/CustomActions/CustomActions.def | 1 + res/msi/CustomActions/CustomActions.vcxproj | 1 + res/msi/CustomActions/FirewallRules.cpp | 430 ++++++++++++++++++ res/msi/Package/Components/RustDesk.wxs | 12 +- .../Package/Fragments/AddRemoveProperties.wxs | 8 +- res/msi/Package/Fragments/CustomActions.wxs | 3 + res/msi/Package/Language/Package.en-us.wxl | 2 +- res/msi/Package/Package.wxs | 3 +- res/msi/preprocess.py | 38 +- 11 files changed, 594 insertions(+), 34 deletions(-) create mode 100644 res/msi/CustomActions/FirewallRules.cpp diff --git a/.github/workflows/flutter-build.yml b/.github/workflows/flutter-build.yml index ed90d1219..0e65c8827 100644 --- a/.github/workflows/flutter-build.yml +++ b/.github/workflows/flutter-build.yml @@ -162,6 +162,18 @@ jobs: mkdir -p ./SignOutput mv ./target/release/rustdesk-portable-packer.exe ./SignOutput/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.exe + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v2 + + - name: Build msi + run: | + pushd ./res/msi + python preprocess.py -arp -d ../../rustdesk + nuget restore msi.sln + msbuild msi.sln -p:Configuration=Release -p:Platform=x64 /p:TargetVersion=Windows10 + mv ./Package/bin/x64/Release/en-us/Package.msi ../../SignOutput/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}-beta.msi + sha256sum ../../SignOutput/rustdesk-*.msi + - name: Sign rustdesk self-extracted file if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '' shell: bash @@ -175,6 +187,7 @@ jobs: prerelease: true tag_name: ${{ env.TAG_NAME }} files: | + ./SignOutput/rustdesk-*.msi ./SignOutput/rustdesk-*.exe ./rustdesk-*.tar.gz diff --git a/res/msi/CustomActions/CustomActions.cpp b/res/msi/CustomActions/CustomActions.cpp index 209b31a89..66ea6e473 100644 --- a/res/msi/CustomActions/CustomActions.cpp +++ b/res/msi/CustomActions/CustomActions.cpp @@ -5,6 +5,10 @@ #include #include #include +#include +#include + +#pragma comment(lib, "Shlwapi.lib") UINT __stdcall CustomActionHello( __in MSIHANDLE hInstall) @@ -206,3 +210,116 @@ LExit: er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); } + +// No use for now, it can be refer as an example of ShellExecuteW. +void AddFirewallRuleCmdline(LPWSTR exeName, LPWSTR exeFile, LPCWSTR dir) +{ + HRESULT hr = S_OK; + HINSTANCE hi = 0; + WCHAR cmdline[1024] = { 0, }; + WCHAR rulename[500] = { 0, }; + + StringCchPrintfW(rulename, sizeof(rulename) / sizeof(rulename[0]), L"%ls Service", exeName); + if (hr < 0) { + WcaLog(LOGMSG_STANDARD, "Failed to make rulename: %ls", exeName); + return; + } + + StringCchPrintfW(cmdline, sizeof(cmdline) / sizeof(cmdline[0]), L"advfirewall firewall add rule name=\"%ls\" dir=%ls action=allow program=\"%ls\" enable=yes", rulename, dir, exeFile); + if (hr < 0) { + WcaLog(LOGMSG_STANDARD, "Failed to make cmdline: %ls", exeName); + return; + } + + hi = ShellExecuteW(NULL, L"open", L"netsh", cmdline, NULL, SW_HIDE); + // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew + if ((int)hi <= 32) { + WcaLog(LOGMSG_STANDARD, "Failed to change firewall rule : %d, last error: %d", (int)hi, GetLastError()); + } + else { + WcaLog(LOGMSG_STANDARD, "Firewall rule \"%ls\" (%ls) is added", rulename, dir); + } +} + +// No use for now, it can be refer as an example of ShellExecuteW. +void RemoveFirewallRuleCmdline(LPWSTR exeName) +{ + HRESULT hr = S_OK; + HINSTANCE hi = 0; + WCHAR cmdline[1024] = { 0, }; + WCHAR rulename[500] = { 0, }; + + StringCchPrintfW(rulename, sizeof(rulename) / sizeof(rulename[0]), L"%ls Service", exeName); + if (hr < 0) { + WcaLog(LOGMSG_STANDARD, "Failed to make rulename: %ls", exeName); + return; + } + + StringCchPrintfW(cmdline, sizeof(cmdline) / sizeof(cmdline[0]), L"advfirewall firewall delete rule name=\"%ls\"", rulename); + if (hr < 0) { + WcaLog(LOGMSG_STANDARD, "Failed to make cmdline: %ls", exeName); + return; + } + + hi = ShellExecuteW(NULL, L"open", L"netsh", cmdline, NULL, SW_HIDE); + // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew + if ((int)hi <= 32) { + WcaLog(LOGMSG_STANDARD, "Failed to change firewall rule \"%ls\" : %d, last error: %d", rulename, (int)hi, GetLastError()); + } + else { + WcaLog(LOGMSG_STANDARD, "Firewall rule \"%ls\" is removed", rulename); + } +} + +bool AddFirewallRule(bool add, LPWSTR exeName, LPWSTR exeFile); +UINT __stdcall AddFirewallRules( + __in MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + int nResult = 0; + LPWSTR exeFile = NULL; + LPWSTR exeName = NULL; + WCHAR exeNameNoExt[500] = { 0, }; + LPWSTR pwz = NULL; + LPWSTR pwzData = NULL; + size_t szNameLen = 0; + + hr = WcaInitialize(hInstall, "AddFirewallExceptions"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = WcaGetProperty(L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + pwz = pwzData; + hr = WcaReadStringFromCaData(&pwz, &exeFile); + ExitOnFailure(hr, "failed to read database key from custom action data: %ls", pwz); + WcaLog(LOGMSG_STANDARD, "Try add firewall exceptions for file : %ls", exeFile); + + exeName = PathFindFileNameW(exeFile + 1); + hr = StringCchPrintfW(exeNameNoExt, 500, exeName); + ExitOnFailure(hr, "Failed to copy exe name: %ls", exeName); + szNameLen = wcslen(exeNameNoExt); + if (szNameLen >= 4 && wcscmp(exeNameNoExt + szNameLen - 4, L".exe") == 0) { + exeNameNoExt[szNameLen - 4] = L'\0'; + } + + //if (exeFile[0] == L'1') { + // AddFirewallRuleCmdline(exeNameNoExt, exeFile, L"in"); + // AddFirewallRuleCmdline(exeNameNoExt, exeFile, L"out"); + //} + //else { + // RemoveFirewallRuleCmdline(exeNameNoExt); + //} + + AddFirewallRule(exeFile[0] == L'1', exeNameNoExt, exeFile + 1); + +LExit: + if (pwzData) { + ReleaseStr(pwzData); + } + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/res/msi/CustomActions/CustomActions.def b/res/msi/CustomActions/CustomActions.def index 0673ee1ad..31a10eb63 100644 --- a/res/msi/CustomActions/CustomActions.def +++ b/res/msi/CustomActions/CustomActions.def @@ -4,3 +4,4 @@ EXPORTS CustomActionHello RemoveInstallFolder TerminateProcesses + AddFirewallRules diff --git a/res/msi/CustomActions/CustomActions.vcxproj b/res/msi/CustomActions/CustomActions.vcxproj index b9491b73b..fcadf9a76 100644 --- a/res/msi/CustomActions/CustomActions.vcxproj +++ b/res/msi/CustomActions/CustomActions.vcxproj @@ -60,6 +60,7 @@ + Create diff --git a/res/msi/CustomActions/FirewallRules.cpp b/res/msi/CustomActions/FirewallRules.cpp new file mode 100644 index 000000000..9381f8f61 --- /dev/null +++ b/res/msi/CustomActions/FirewallRules.cpp @@ -0,0 +1,430 @@ +// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ics/c-adding-an-application-rule-edge-traversal + +/******************************************************************** +Copyright (C) Microsoft. All Rights Reserved. + +Abstract: + This C++ file includes sample code that adds a firewall rule with + EdgeTraversalOptions (one of the EdgeTraversalOptions values). + +********************************************************************/ + +#include "pch.h" +#include +#include +#include +#include + +#pragma comment(lib, "ole32.lib") +#pragma comment(lib, "oleaut32.lib") + +#define STRING_BUFFER_SIZE 500 + + +// Forward declarations +HRESULT WFCOMInitialize(INetFwPolicy2** ppNetFwPolicy2); +void WFCOMCleanup(INetFwPolicy2* pNetFwPolicy2); +HRESULT RemoveFirewallRule( + __in INetFwPolicy2* pNetFwPolicy2, + __in LPWSTR exeName); +HRESULT AddFirewallRuleWithEdgeTraversal(__in INetFwPolicy2* pNetFwPolicy2, + __in bool in, + __in LPWSTR exeName, + __in LPWSTR exeFile); + + +bool AddFirewallRule(bool add, LPWSTR exeName, LPWSTR exeFile) +{ + bool result = false; + HRESULT hrComInit = S_OK; + HRESULT hr = S_OK; + INetFwPolicy2* pNetFwPolicy2 = NULL; + + // Initialize COM. + hrComInit = CoInitializeEx( + 0, + COINIT_APARTMENTTHREADED + ); + + // Ignore RPC_E_CHANGED_MODE; this just means that COM has already been + // initialized with a different mode. Since we don't care what the mode is, + // we'll just use the existing mode. + if (hrComInit != RPC_E_CHANGED_MODE) + { + if (FAILED(hrComInit)) + { + WcaLog(LOGMSG_STANDARD, "CoInitializeEx failed: 0x%08lx\n", hrComInit); + goto Cleanup; + } + } + + // Retrieve INetFwPolicy2 + hr = WFCOMInitialize(&pNetFwPolicy2); + if (FAILED(hr)) + { + goto Cleanup; + } + + if (add) { + // Add firewall rule with EdgeTraversalOption=DeferApp (Windows7+) if available + // else add with Edge=True (Vista and Server 2008). + hr = AddFirewallRuleWithEdgeTraversal(pNetFwPolicy2, true, exeName, exeFile); + hr = AddFirewallRuleWithEdgeTraversal(pNetFwPolicy2, false, exeName, exeFile); + } + else { + hr = RemoveFirewallRule(pNetFwPolicy2, exeName); + } + result = SUCCEEDED(hr); + +Cleanup: + + // Release INetFwPolicy2 + WFCOMCleanup(pNetFwPolicy2); + + // Uninitialize COM. + if (SUCCEEDED(hrComInit)) + { + CoUninitialize(); + } + + return result; +} + +BSTR MakeRuleName(__in LPWSTR exeName) +{ + WCHAR pwszTemp[STRING_BUFFER_SIZE] = L""; + HRESULT hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, L"%ls Service", exeName); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to compose a resource identifier string: 0x%08lx\n", hr); + return NULL; + } + return SysAllocString(pwszTemp); +} + +HRESULT RemoveFirewallRule( + __in INetFwPolicy2* pNetFwPolicy2, + __in LPWSTR exeName) +{ + HRESULT hr = S_OK; + INetFwRules* pNetFwRules = NULL; + + WCHAR pwszTemp[STRING_BUFFER_SIZE] = L""; + + BSTR RuleName = NULL; + + RuleName = MakeRuleName(exeName); + if (NULL == RuleName) + { + WcaLog(LOGMSG_STANDARD, "\nERROR: Insufficient memory\n"); + goto Cleanup; + } + + hr = pNetFwPolicy2->get_Rules(&pNetFwRules); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to retrieve firewall rules collection : 0x%08lx\n", hr); + goto Cleanup; + } + + // We need to "Remove()" twice, because both "in" and "out" rules are added? + // There's no remarks for this case https://learn.microsoft.com/en-us/windows/win32/api/netfw/nf-netfw-inetfwrules-remove + hr = pNetFwRules->Remove(RuleName); + hr = pNetFwRules->Remove(RuleName); + if (FAILED(hr)) { + WcaLog(LOGMSG_STANDARD, "Failed to remove firewall rule \"%ls\" : 0x%08lx\n", exeName, hr); + } + else { + WcaLog(LOGMSG_STANDARD, "Firewall rule \"%ls\" is removed\n", exeName); + } + +Cleanup: + + SysFreeString(RuleName); + + if (pNetFwRules != NULL) + { + pNetFwRules->Release(); + } + + return hr; +} + +// Add firewall rule with EdgeTraversalOption=DeferApp (Windows7+) if available +// else add with Edge=True (Vista and Server 2008). +HRESULT AddFirewallRuleWithEdgeTraversal( + __in INetFwPolicy2* pNetFwPolicy2, + __in bool in, + __in LPWSTR exeName, + __in LPWSTR exeFile) +{ + HRESULT hr = S_OK; + INetFwRules* pNetFwRules = NULL; + + INetFwRule* pNetFwRule = NULL; + INetFwRule2* pNetFwRule2 = NULL; + + WCHAR pwszTemp[STRING_BUFFER_SIZE] = L""; + + BSTR RuleName = NULL; + BSTR RuleGroupName = NULL; + BSTR RuleDescription = NULL; + BSTR RuleAppPath = NULL; + + long CurrentProfilesBitMask = 0; + + + // For localization purposes, the rule name, description, and group can be + // provided as indirect strings. These indirect strings can be defined in an rc file. + // Examples of the indirect string definitions in the rc file - + // 127 "EdgeTraversalOptions Sample Application" + // 128 "Allow inbound TCP traffic to application EdgeTraversalOptions.exe" + // 129 "Allow EdgeTraversalOptions.exe to receive inbound traffic for TCP protocol + // from remote machines located within your network as well as from + // the Internet (i.e from outside of your Edge device like Firewall or NAT" + + + // Examples of using indirect strings - + // hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, L"@EdgeTraversalOptions.exe,-128"); + RuleName = MakeRuleName(exeName); + if (NULL == RuleName) + { + WcaLog(LOGMSG_STANDARD, "\nERROR: Insufficient memory\n"); + goto Cleanup; + } + // Examples of using indirect strings - + // hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, L"@EdgeTraversalOptions.exe,-127"); + hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, exeName); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to compose a resource identifier string: 0x%08lx\n", hr); + goto Cleanup; + } + RuleGroupName = SysAllocString(pwszTemp); // Used for grouping together multiple rules + if (NULL == RuleGroupName) + { + WcaLog(LOGMSG_STANDARD, "\nERROR: Insufficient memory\n"); + goto Cleanup; + } + // Examples of using indirect strings - + // hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, L"@EdgeTraversalOptions.exe,-129"); + hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, L"Allow %ls to receive \ + inbound traffic from remote machines located within your network as well as \ + from the Internet", exeName); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to compose a resource identifier string: 0x%08lx\n", hr); + goto Cleanup; + } + RuleDescription = SysAllocString(pwszTemp); + if (NULL == RuleDescription) + { + WcaLog(LOGMSG_STANDARD, "\nERROR: Insufficient memory\n"); + goto Cleanup; + } + + RuleAppPath = SysAllocString(exeFile); + if (NULL == RuleAppPath) + { + WcaLog(LOGMSG_STANDARD, "\nERROR: Insufficient memory\n"); + goto Cleanup; + } + + hr = pNetFwPolicy2->get_Rules(&pNetFwRules); + + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to retrieve firewall rules collection : 0x%08lx\n", hr); + goto Cleanup; + } + + hr = CoCreateInstance( + __uuidof(NetFwRule), //CLSID of the class whose object is to be created + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(INetFwRule), // Identifier of the Interface used for communicating with the object + (void**)&pNetFwRule); + + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "CoCreateInstance for INetFwRule failed: 0x%08lx\n", hr); + goto Cleanup; + } + + hr = pNetFwRule->put_Name(RuleName); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Name failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + hr = pNetFwRule->put_Grouping(RuleGroupName); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Grouping failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + hr = pNetFwRule->put_Description(RuleDescription); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Description failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + if (in) { + CurrentProfilesBitMask = NET_FW_PROFILE2_ALL; + } + else { + // Retrieve Current Profiles bitmask + hr = pNetFwPolicy2->get_CurrentProfileTypes(&CurrentProfilesBitMask); + if (FAILED(hr)) + { + printf("get_CurrentProfileTypes failed: 0x%08lx\n", hr); + goto Cleanup; + } + + // When possible we avoid adding firewall rules to the Public profile. + // If Public is currently active and it is not the only active profile, we remove it from the bitmask + if ((CurrentProfilesBitMask & NET_FW_PROFILE2_PUBLIC) && + (CurrentProfilesBitMask != NET_FW_PROFILE2_PUBLIC)) + { + CurrentProfilesBitMask ^= NET_FW_PROFILE2_PUBLIC; + } + } + + hr = pNetFwRule->put_Direction(in ? NET_FW_RULE_DIR_IN : NET_FW_RULE_DIR_OUT); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Direction failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + + hr = pNetFwRule->put_Action(NET_FW_ACTION_ALLOW); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Action failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + hr = pNetFwRule->put_ApplicationName(RuleAppPath); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_ApplicationName failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + //hr = pNetFwRule->put_Protocol(6); // TCP + //if (FAILED(hr)) + //{ + // WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Protocol failed with error: 0x %x.\n", hr); + // goto Cleanup; + //} + + hr = pNetFwRule->put_Profiles(CurrentProfilesBitMask); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Profiles failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + hr = pNetFwRule->put_Enabled(VARIANT_TRUE); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_Enabled failed with error: 0x %x.\n", hr); + goto Cleanup; + } + + if (in) { + // Check if INetFwRule2 interface is available (i.e Windows7+) + // If supported, then use EdgeTraversalOptions + // Else use the EdgeTraversal boolean flag. + + if (SUCCEEDED(pNetFwRule->QueryInterface(__uuidof(INetFwRule2), (void**)&pNetFwRule2))) + { + hr = pNetFwRule2->put_EdgeTraversalOptions(NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_EdgeTraversalOptions failed with error: 0x %x.\n", hr); + goto Cleanup; + } + } + else + { + hr = pNetFwRule->put_EdgeTraversal(VARIANT_TRUE); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed INetFwRule::put_EdgeTraversal failed with error: 0x %x.\n", hr); + goto Cleanup; + } + } + } + + hr = pNetFwRules->Add(pNetFwRule); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to add firewall rule to the firewall rules collection : 0x%08lx\n", hr); + goto Cleanup; + } + + WcaLog(LOGMSG_STANDARD, "Successfully added firewall rule !\n"); + +Cleanup: + + SysFreeString(RuleName); + SysFreeString(RuleGroupName); + SysFreeString(RuleDescription); + SysFreeString(RuleAppPath); + + if (pNetFwRule2 != NULL) + { + pNetFwRule2->Release(); + } + + if (pNetFwRule != NULL) + { + pNetFwRule->Release(); + } + + if (pNetFwRules != NULL) + { + pNetFwRules->Release(); + } + + return hr; +} + + +// Instantiate INetFwPolicy2 +HRESULT WFCOMInitialize(INetFwPolicy2** ppNetFwPolicy2) +{ + HRESULT hr = S_OK; + + hr = CoCreateInstance( + __uuidof(NetFwPolicy2), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(INetFwPolicy2), + (void**)ppNetFwPolicy2); + + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "CoCreateInstance for INetFwPolicy2 failed: 0x%08lx\n", hr); + goto Cleanup; + } + +Cleanup: + return hr; +} + + +// Release INetFwPolicy2 +void WFCOMCleanup(INetFwPolicy2* pNetFwPolicy2) +{ + // Release the INetFwPolicy2 object (Vista+) + if (pNetFwPolicy2 != NULL) + { + pNetFwPolicy2->Release(); + } +} diff --git a/res/msi/Package/Components/RustDesk.wxs b/res/msi/Package/Components/RustDesk.wxs index f01c4999d..ffd30270a 100644 --- a/res/msi/Package/Components/RustDesk.wxs +++ b/res/msi/Package/Components/RustDesk.wxs @@ -7,7 +7,7 @@ - + @@ -18,6 +18,8 @@ + + - + + + + + + + diff --git a/res/msi/Package/Fragments/AddRemoveProperties.wxs b/res/msi/Package/Fragments/AddRemoveProperties.wxs index 56dfb1854..5711aa5a8 100644 --- a/res/msi/Package/Fragments/AddRemoveProperties.wxs +++ b/res/msi/Package/Fragments/AddRemoveProperties.wxs @@ -22,12 +22,8 @@ - - + + - - - - diff --git a/res/msi/Package/Fragments/CustomActions.wxs b/res/msi/Package/Fragments/CustomActions.wxs index 0c1e61e4d..29ae04492 100644 --- a/res/msi/Package/Fragments/CustomActions.wxs +++ b/res/msi/Package/Fragments/CustomActions.wxs @@ -7,5 +7,8 @@ + + + diff --git a/res/msi/Package/Language/Package.en-us.wxl b/res/msi/Package/Language/Package.en-us.wxl index 92f76c106..517bde2af 100644 --- a/res/msi/Package/Language/Package.en-us.wxl +++ b/res/msi/Package/Language/Package.en-us.wxl @@ -47,6 +47,6 @@ 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 cd6b29936..9fbedd9ed 100644 --- a/res/msi/Package/Package.wxs +++ b/res/msi/Package/Package.wxs @@ -22,8 +22,7 @@ - - + diff --git a/res/msi/preprocess.py b/res/msi/preprocess.py index b91d2302f..f051db5ee 100644 --- a/res/msi/preprocess.py +++ b/res/msi/preprocess.py @@ -38,10 +38,7 @@ g_arpsystemcomponent = { def make_parser(): parser = argparse.ArgumentParser(description="Msi preprocess script.") parser.add_argument( - "-d", "--debug", action="store_true", help="Is debug", default=False - ) - parser.add_argument( - "-ci", "--github-ci", action="store_true", help="Is github ci", default=False + "-d", "--dist-dir", type=str, default="../../rustdesk", help="The dist direcotry to install." ) parser.add_argument( "-arp", @@ -96,9 +93,9 @@ def read_lines_and_start_index(file_path, tag_start, tag_end): return lines, index_start -def insert_components_between_tags(lines, index_start, app_name, build_dir): +def insert_components_between_tags(lines, index_start, app_name, dist_dir): indent = g_indent_unit * 3 - path = Path(build_dir) + path = Path(dist_dir) idx = 1 for file_path in path.glob("**/*"): if file_path.is_file(): @@ -129,18 +126,18 @@ def insert_components_between_tags(lines, index_start, app_name, build_dir): return True -def gen_auto_component(app_name, build_dir): +def gen_auto_component(app_name, dist_dir): return gen_content_between_tags( "Package/Components/RustDesk.wxs", "", "", lambda lines, index_start: insert_components_between_tags( - lines, index_start, app_name, build_dir + lines, index_start, app_name, dist_dir ), ) -def gen_pre_vars(args, build_dir): +def gen_pre_vars(args, dist_dir): def func(lines, index_start): upgrade_code = uuid.uuid5(uuid.NAMESPACE_OID, app_name + ".exe") @@ -153,7 +150,7 @@ def gen_pre_vars(args, build_dir): f'{indent}\n', f'{indent}\n', f'{indent}\n', - f'{indent}\n', + f'{indent}\n', f'{indent}\n', "\n", f"{indent}\n" @@ -278,7 +275,7 @@ def get_folder_size(folder_path): return total_size -def gen_custom_ARPSYSTEMCOMPONENT_True(args, build_dir): +def gen_custom_ARPSYSTEMCOMPONENT_True(args, dist_dir): def func(lines, index_start): indent = g_indent_unit * 5 @@ -312,7 +309,7 @@ def gen_custom_ARPSYSTEMCOMPONENT_True(args, build_dir): f'{indent}\n' ) - estimated_size = get_folder_size(build_dir) + estimated_size = get_folder_size(dist_dir) lines_new.append( f'{indent}\n' ) @@ -359,7 +356,7 @@ def gen_custom_ARPSYSTEMCOMPONENT_True(args, build_dir): ) -def gen_custom_ARPSYSTEMCOMPONENT(args, build_dir): +def gen_custom_ARPSYSTEMCOMPONENT(args, dist_dir): try: custom_arp = json.loads(args.custom_arp) g_arpsystemcomponent.update(custom_arp) @@ -368,7 +365,7 @@ def gen_custom_ARPSYSTEMCOMPONENT(args, build_dir): return False if args.arp: - return gen_custom_ARPSYSTEMCOMPONENT_True(args, build_dir) + return gen_custom_ARPSYSTEMCOMPONENT_True(args, dist_dir) else: return gen_custom_ARPSYSTEMCOMPONENT_False(args) @@ -427,26 +424,21 @@ if __name__ == "__main__": args = parser.parse_args() app_name = args.app_name - build_dir = ( - f'../../flutter/build/windows/x64/runner/{"Debug" if args.debug else "Release"}' - ) - if args.github_ci: - build_dir = "../../rustdesk" - build_dir = Path(sys.argv[0]).parent.joinpath(build_dir).resolve() + dist_dir = Path(sys.argv[0]).parent.joinpath(args.dist_dir).resolve() if not init_global_vars(args): sys.exit(-1) - if not gen_pre_vars(args, build_dir): + if not gen_pre_vars(args, dist_dir): sys.exit(-1) if not gen_upgrade_info(): sys.exit(-1) - if not gen_custom_ARPSYSTEMCOMPONENT(args, build_dir): + if not gen_custom_ARPSYSTEMCOMPONENT(args, dist_dir): sys.exit(-1) - if not gen_auto_component(app_name, build_dir): + if not gen_auto_component(app_name, dist_dir): sys.exit(-1) if not gen_custom_dialog_bitmaps():