Refact/msi more install options (#8949)

* refact: msi, more install options

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

* refact: msi, reg values on upgrade/modify

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

* fix: msi, silent repair/upgrade, RemoveInstallFolder()

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

* Options support both 1/0 and Y/N

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

* refact: msi, preprocess, open file with explicit encoding

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

* fix: msi, read previous options

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

* fix: mis, install folder, read previous option

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

* Comment on Control -> Checkbox

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

* fix: UI, checkbox options, read previous values

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

* fix: shortcuts options, init state

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

* fix: shortcuts, init state

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

* Better shortcuts property conditions

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

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2024-08-05 17:49:48 +08:00 committed by GitHub
parent 2266fde26f
commit b3e1c8a907
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 209 additions and 46 deletions

View File

@ -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:

View File

@ -3,8 +3,26 @@
<?include ../Includes.wxi?>
<Fragment>
<!-- For compatibility with command line values from previous versions -->
<Property Id="INSTALLFOLDER" Secure="yes">
<RegistrySearch Id="InstallFolderSearch" Root="HKCR" Key="$(var.RegKeyRoot)" Name="INSTALLFOLDER" Type="raw" />
</Property>
<!-- If a property value has been passed via the command line (which includes when set from the bundle), the registry search will
overwrite the command line value, these actions temporarily store the command line value before the registry search
is performed so they can be restored after the registry search is complete -->
<SetProperty Id="SavedInstallFolderCmdLineValue" Value="[INSTALLFOLDER]" Before="AppSearch" Sequence="first" Condition="INSTALLFOLDER" />
<!-- If a command line value was stored, restore it after the registry search has been performed -->
<SetProperty Action="RestoreSavedInstallFolderValue" Id="INSTALLFOLDER" Value="[SavedInstallFolderCmdLineValue]" After="AppSearch" Sequence="first" Condition="SavedInstallFolderCmdLineValue" />
<!-- If a command line value or registry value was set, update the main properties with the value -->
<SetProperty Id="INSTALLFOLDER_INNER" Value="[INSTALLFOLDER]" After="RestoreSavedInstallFolderValue" Sequence="first" Condition="INSTALLFOLDER" />
<!-- INSTALLFOLDER_INNER is defined for compatibility with previous versions of the installer. -->
<!-- Because we need to use INSTALLFOLDER as the command line argument. -->
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="$(var.Product)" />
<Directory Id="INSTALLFOLDER_INNER" Name="$(var.Product)" />
</StandardDirectory>
<StandardDirectory Id="CommonAppDataFolder">

View File

@ -5,16 +5,16 @@
<Fragment>
<!-- Regs for shortcuts are defined in "Fragments/ShortcutProperties.wxs" -->
<!-- Component that persists the property values to the registry so they are available during an upgrade/modify -->
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="Product.Registry.InstallDir" Guid="3196EDA7-9AEF-4705-A0C8-E3F3ECCCB153">
<DirectoryRef Id="INSTALLFOLDER_INNER">
<Component Id="Product.Registry.InstallFolder" Guid="3196EDA7-9AEF-4705-A0C8-E3F3ECCCB153">
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)">
<RegistryValue Type="string" Name="INSTALLFOLDER" Value="[INSTALLFOLDER]" />
<RegistryValue Type="string" Name="INSTALLFOLDER" Value="[INSTALLFOLDER_INNER]" />
</RegistryKey>
</Component>
<Component Id="Product.Registry.DefaultIcon" Guid="6DBF2690-0955-4C6A-940F-634DDA503F49">
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)\DefaultIcon">
<RegistryValue Type="string" Value='"[INSTALLFOLDER]$(var.Product).exe",0' />
<RegistryValue Type="string" Value='"[INSTALLFOLDER_INNER]$(var.Product).exe",0' />
</RegistryKey>
</Component>
@ -22,7 +22,7 @@
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)\shell" />
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)\shell\open" />
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)\shell\open\command">
<RegistryValue Type="string" Value='"[INSTALLFOLDER]$(var.Product).exe" --play "%1"' />
<RegistryValue Type="string" Value='"[INSTALLFOLDER_INNER]$(var.Product).exe" --play "%1"' />
</RegistryKey>
</Component>
@ -36,7 +36,7 @@
<RegistryKey Root="HKCR" Key="$(var.ProductLower)\shell" />
<RegistryKey Root="HKCR" Key="$(var.ProductLower)\shell\open" />
<RegistryKey Root="HKCR" Key="$(var.ProductLower)\shell\open\command">
<RegistryValue Type="string" Value='"[INSTALLFOLDER]$(var.Product).exe" "%1"' />
<RegistryValue Type="string" Value='"[INSTALLFOLDER_INNER]$(var.Product).exe" "%1"' />
</RegistryKey>
</Component>

View File

@ -4,7 +4,7 @@
<?include ../Includes.wxi?>
<DirectoryRef Id="INSTALLFOLDER" FileSource="$(var.BuildDir)">
<DirectoryRef Id="INSTALLFOLDER_INNER" FileSource="$(var.BuildDir)">
<Component Id="App.exe" Guid="620F0F69-4C17-4320-A619-495E329712A4">
<File Id="App.exe" Name="$(var.Product).exe" KeyPath="yes" Checksum="yes">
<!--<fire:FirewallException Id="AppEx" Name="$(var.Product) Service" Scope="any" IgnoreFailure="yes" />-->
@ -12,10 +12,10 @@
</Component>
</DirectoryRef>
<CustomAction Id="RemoveInstallFolder.SetParam" Return="check" Property="RemoveInstallFolder" Value="[INSTALLFOLDER]" />
<CustomAction Id="AddFirewallRules.SetParam" Return="check" Property="AddFirewallRules" Value="1[INSTALLFOLDER]$(var.Product).exe" />
<CustomAction Id="RemoveFirewallRules.SetParam" Return="check" Property="RemoveFirewallRules" Value="0[INSTALLFOLDER]$(var.Product).exe" />
<CustomAction Id="CreateStartService.SetParam" Return="check" Property="CreateStartService" Value="$(var.Product);&quot;[INSTALLFOLDER]$(var.Product).exe&quot; --service" />
<CustomAction Id="RemoveInstallFolder.SetParam" Return="check" Property="RemoveInstallFolder" Value="[INSTALLFOLDER_INNER]" />
<CustomAction Id="AddFirewallRules.SetParam" Return="check" Property="AddFirewallRules" Value="1[INSTALLFOLDER_INNER]$(var.Product).exe" />
<CustomAction Id="RemoveFirewallRules.SetParam" Return="check" Property="RemoveFirewallRules" Value="0[INSTALLFOLDER_INNER]$(var.Product).exe" />
<CustomAction Id="CreateStartService.SetParam" Return="check" Property="CreateStartService" Value="$(var.Product);&quot;[INSTALLFOLDER_INNER]$(var.Product).exe&quot; --service" />
<CustomAction Id="TryStopDeleteService.SetParam" Return="check" Property="TryStopDeleteService" Value="$(var.Product)" />
<CustomAction Id="LaunchApp" ExeCommand="" Return="asyncNoWait" FileRef="App.exe" />
@ -29,7 +29,7 @@
<CustomAction Id="SetPropertyServiceStop.SetParam.ConfigKey" Return="check" Property="ConfigKey" Value="stop-service" />
<CustomAction Id="SetPropertyServiceStop.SetParam.PropertyName" Return="check" Property="PropertyName" Value="STOP_SERVICE" />
<CustomAction Id="TryDeleteStartupShortcut.SetParam" Return="check" Property="ShortcutName" Value="$(var.Product) Tray" />
<CustomAction Id="RemoveAmyuniIdd.SetParam" Return="check" Property="RemoveAmyuniIdd" Value="[INSTALLFOLDER]" />
<CustomAction Id="RemoveAmyuniIdd.SetParam" Return="check" Property="RemoveAmyuniIdd" Value="[INSTALLFOLDER_INNER]" />
<InstallExecuteSequence>
<Custom Action="SetPropertyIsServiceRunning" After="InstallInitialize" Condition="Installed" />
@ -88,8 +88,8 @@
</DirectoryRef>
<DirectoryRef Id="App.StartMenu">
<Component Id="App.StartMenu.Shortcut" Guid="43ABCAC7-E47D-42D8-A408-25EC70DBB993" Condition="STARTMENUSHORTCUTS = 1">
<Shortcut Id="App.StartMenu.Shortcut" Name="!(loc.SC_Client)" Description="!(loc.SC_Client_Desc)" Target="[!App.exe]" Icon="AppIcon" WorkingDirectory="INSTALLFOLDER" />
<Component Id="App.StartMenu.Shortcut" Guid="43ABCAC7-E47D-42D8-A408-25EC70DBB993" Condition="STARTMENUSHORTCUTS = 1 OR STARTMENUSHORTCUTS = &quot;Y&quot; OR STARTMENUSHORTCUTS = &quot;y&quot;">
<Shortcut Id="App.StartMenu.Shortcut" Name="!(loc.SC_Client)" Description="!(loc.SC_Client_Desc)" Target="[!App.exe]" Icon="AppIcon" WorkingDirectory="INSTALLFOLDER_INNER" />
<!--
Fix ICE 38 by adding a dummy registry key that is the key for this shortcut.
https://learn.microsoft.com/en-us/windows/win32/msi/ice38
@ -97,31 +97,31 @@
<RegistryValue Root="HKCU" Key="Software\$(var.Product)" Name="App.StartMenu.Shortcut" Type="string" Value="1" KeyPath="yes" />
</Component>
<Component Id="App.StartMenu.ShortcutUninstall" Guid="E100D7F8-D607-4513-28DA-2C95E5EA698E" Condition="STARTMENUSHORTCUTS = 1">
<Component Id="App.StartMenu.ShortcutUninstall" Guid="E100D7F8-D607-4513-28DA-2C95E5EA698E" Condition="STARTMENUSHORTCUTS = 1 OR STARTMENUSHORTCUTS = &quot;Y&quot; OR STARTMENUSHORTCUTS = &quot;y&quot;">
<Shortcut Id="App.StartMenu.ShortcutUninstall" Name="!(loc.SC_Uninstall)" Description="!(loc.SC_Uninstall_Desc)" Target="[System6432Folder]msiexec.exe" Arguments="/x [ProductCode]" Icon="AppIcon" />
<RegistryValue Root="HKCU" Key="Software\$(var.Product)" Name="App.StartMenu.ShortcutUninstall" Type="string" Value="1" KeyPath="yes" />
</Component>
</DirectoryRef>
<StandardDirectory Id="DesktopFolder">
<Component Id="App.Desktop.Shortcut" Guid="CA8FB7AA-17F7-4E36-A58A-5A016A303709" Condition="DESKTOPSHORTCUTS = 1">
<Shortcut Id="App.Desktop.Shortcut" Name="!(loc.SC_Client)" Description="!(loc.SC_Client_Desc)" Target="[!App.exe]" Icon="AppIcon" WorkingDirectory="INSTALLFOLDER" />
<Component Id="App.Desktop.Shortcut" Guid="CA8FB7AA-17F7-4E36-A58A-5A016A303709" Condition="DESKTOPSHORTCUTS = 1 OR DESKTOPSHORTCUTS = &quot;Y&quot; OR DESKTOPSHORTCUTS = &quot;y&quot;">
<Shortcut Id="App.Desktop.Shortcut" Name="!(loc.SC_Client)" Description="!(loc.SC_Client_Desc)" Target="[!App.exe]" Icon="AppIcon" WorkingDirectory="INSTALLFOLDER_INNER" />
<RegistryValue Root="HKCU" Key="Software\$(var.Product)" Name="App.Desktop.Shortcut" Type="string" Value="1" KeyPath="yes" />
</Component>
</StandardDirectory>
<StandardDirectory Id="StartupFolder">
<Component Id="App.StartupFolder.ShortcutTray" Guid="B1D1E2BB-E53E-E159-DB7C-744D5C726A8C" Condition="STARTUPSHORTCUTS = 1 AND (NOT CC_CONNECTION_TYPE=&quot;outgoing&quot;)">
<Shortcut Id="App.StartupFolder.ShortcutTray" Name="!(loc.SC_Client_Tray)" Description="!(loc.SC_Client_Tray_Desc)" Target="[!App.exe]" Arguments="--tray" Icon="AppIcon" WorkingDirectory="INSTALLFOLDER" />
<Shortcut Id="App.StartupFolder.ShortcutTray" Name="!(loc.SC_Client_Tray)" Description="!(loc.SC_Client_Tray_Desc)" Target="[!App.exe]" Arguments="--tray" Icon="AppIcon" WorkingDirectory="INSTALLFOLDER_INNER" />
<RegistryValue Root="HKCU" Key="Software\$(var.Product)" Name="App.StartupFolder.ShortcutTray" Type="string" Value="1" KeyPath="yes" />
</Component>
</StandardDirectory>
<!--<DirectoryRef Id="INSTALLFOLDER">
<!--<DirectoryRef Id="INSTALLFOLDER_INNER">
<Component Id="App.UninstallShortcut" Guid="FB0F2AC7-2AE5-4C54-B860-5E472620B6B1">
<Shortcut Id="App.UninstallShortcut" Name="!(loc.SC_Uninstall)" Description="!(loc.SC_Uninstall_Desc)" Target="[System6432Folder]msiexec.exe" Arguments="/x [ProductCode]" Icon="AppIcon" />
</Component>
</DirectoryRef>-->
<ComponentGroup Id="Components" Directory="INSTALLFOLDER">
<ComponentGroup Id="Components" Directory="INSTALLFOLDER_INNER">
<ComponentRef Id="App.exe" />
<ComponentRef Id="App.Desktop.Shortcut" />
<!--<ComponentRef Id="App.UninstallShortcut" />-->

View File

@ -25,11 +25,25 @@
</Property>
<!-- Component that persists the property values to the registry so they are available during an upgrade/modify -->
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="Product.Registry.PersistedShortcutProperties" Guid="1BBAD054-6EC2-4362-BF1B-E8BDE988B597">
<DirectoryRef Id="INSTALLFOLDER_INNER">
<Component Id="Product.Registry.PersistedStartMenuShortcutProperties1" Guid="62F79BCF-3367-4ACF-950F-F8BCABACDDC0" Condition="STARTMENUSHORTCUTS = 1 OR STARTMENUSHORTCUTS = &quot;Y&quot; OR STARTMENUSHORTCUTS = &quot;y&quot;">
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)">
<RegistryValue Type="string" Name="STARTMENUSHORTCUTS" Value="[STARTMENUSHORTCUTS]" KeyPath="yes" />
<RegistryValue Type="string" Name="DESKTOPSHORTCUTS" Value="[DESKTOPSHORTCUTS]" />
<RegistryValue Type="string" Name="STARTMENUSHORTCUTS" Value="1" KeyPath="yes" />
</RegistryKey>
</Component>
<Component Id="Product.Registry.PersistedStartMenuShortcutProperties0" Guid="8EA2D5A8-6E5D-4BDD-9019-2099297FF519" Condition="NOT (STARTMENUSHORTCUTS = 1 OR STARTMENUSHORTCUTS = &quot;Y&quot; OR STARTMENUSHORTCUTS = &quot;y&quot;)">
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)">
<RegistryValue Type="string" Name="STARTMENUSHORTCUTS" Value="0" KeyPath="yes" />
</RegistryKey>
</Component>
<Component Id="Product.Registry.PersistedDesktopShortcutProperties1" Guid="1BBAD054-6EC2-4362-BF1B-E8BDE988B597" Condition="DESKTOPSHORTCUTS = 1 OR DESKTOPSHORTCUTS = &quot;Y&quot; OR DESKTOPSHORTCUTS = &quot;y&quot;">
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)">
<RegistryValue Type="string" Name="DESKTOPSHORTCUTS" Value="1" />
</RegistryKey>
</Component>
<Component Id="Product.Registry.PersistedDesktopShortcutProperties0" Guid="FA992614-D2E1-4795-9696-D45A5EF1B9C8" Condition="NOT (DESKTOPSHORTCUTS = 1 OR DESKTOPSHORTCUTS = &quot;Y&quot; OR DESKTOPSHORTCUTS = &quot;y&quot;)">
<RegistryKey Root="HKCR" Key="$(var.RegKeyRoot)">
<RegistryValue Type="string" Name="DESKTOPSHORTCUTS" Value="0" />
</RegistryKey>
</Component>
</DirectoryRef>
@ -45,8 +59,8 @@
<SetProperty Action="RestoreSavedDesktopShortcutsValue" Id="CREATEDESKTOPSHORTCUTS" Value="[SavedDesktopShortcutsCmdLineValue]" After="AppSearch" Sequence="first" Condition="SavedDesktopShortcutsCmdLineValue" />
<!-- If a command line value or registry value was set, update the main properties with the value -->
<SetProperty Id="STARTMENUSHORTCUTS" Value="[CREATESTARTMENUSHORTCUTS]" After="RestoreSavedStartMenuShortcutsValue" Sequence="first" Condition="CREATESTARTMENUSHORTCUTS" />
<SetProperty Id="DESKTOPSHORTCUTS" Value="[CREATEDESKTOPSHORTCUTS]" After="RestoreSavedDesktopShortcutsValue" Sequence="first" Condition="CREATEDESKTOPSHORTCUTS" />
<SetProperty Id="STARTMENUSHORTCUTS" Value="" After="RestoreSavedStartMenuShortcutsValue" Sequence="first" Condition="CREATESTARTMENUSHORTCUTS AND NOT (CREATESTARTMENUSHORTCUTS = 1 OR CREATESTARTMENUSHORTCUTS = &quot;Y&quot; OR CREATESTARTMENUSHORTCUTS = &quot;y&quot;)" />
<SetProperty Id="DESKTOPSHORTCUTS" Value="" After="RestoreSavedDesktopShortcutsValue" Sequence="first" Condition="CREATEDESKTOPSHORTCUTS AND NOT (CREATEDESKTOPSHORTCUTS = 1 OR CREATEDESKTOPSHORTCUTS = &quot;Y&quot; OR CREATEDESKTOPSHORTCUTS = &quot;y&quot;)" />
</Fragment>
</Wix>

View File

@ -49,4 +49,7 @@ This file contains the declaration of all the localizable strings.
<String Id="AnotherAppDialogTitle" Value="Cancel installation."/>
<String Id="AnotherAppDialogDescription" Value="The application is installed by self-installation method, please uninstall it first."/>
<String Id="MyInstallDirDlgDesktopShortcuts" Value="Create desktop icon" />
<String Id="MyInstallDirDlgStartMenuShortcuts" Value="Create start menu shortcuts" />
</WixLocalization>

View File

@ -18,11 +18,11 @@
<!-- User Interface -->
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
<ui:WixUI Id="WixUI_InstallDir" InstallDirectory="INSTALLFOLDER" />
<ui:WixUI Id="UI_MyInstallDialog" InstallDirectory="INSTALLFOLDER_INNER" />
<UIRef Id="WixUI_ErrorProgressText" />
<InstallUISequence>
<Show Dialog="AnotherAppDialog" Before="WelcomeDlg" Condition="Not installed AND APP_WINDOWS_INSTALLER=&quot;#0&quot;"/>
<Show Dialog="UI_AnotherAppDialog" Before="WelcomeDlg" Condition="Not installed AND APP_WINDOWS_INSTALLER=&quot;#0&quot;"/>
</InstallUISequence>
<InstallExecuteSequence>
@ -40,14 +40,17 @@
<Feature Id="App" Level="1" AllowAdvertise="no" Display="expand" Title="!(loc.F_App)" Description="!(loc.F_App_Desc)" AllowAbsent="no">
<ComponentGroupRef Id="Components" />
<ComponentRef Id="Product.Registry.InstallDir" />
<ComponentRef Id="Product.Registry.InstallFolder" />
<ComponentRef Id="Product.Registry.DefaultIcon" />
<ComponentRef Id="Product.Registry.CommandPlay" />
<ComponentRef Id="Product.Registry.URLProtocol" />
<ComponentRef Id="Product.Registry.Command" />
<ComponentRef Id="Product.Registry.UninstallApp" />
<ComponentRef Id="App.StartMenu" />
<ComponentRef Id="Product.Registry.PersistedShortcutProperties" />
<ComponentRef Id="Product.Registry.PersistedStartMenuShortcutProperties1" />
<ComponentRef Id="Product.Registry.PersistedStartMenuShortcutProperties0" />
<ComponentRef Id="Product.Registry.PersistedDesktopShortcutProperties1" />
<ComponentRef Id="Product.Registry.PersistedDesktopShortcutProperties0" />
</Feature>
<!--https://wixtoolset.org/docs/tools/wixext/wixui/#customizing-a-dialog-set-->

View File

@ -1,7 +1,7 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<UI>
<Dialog Id="AnotherAppDialog" Width="370" Height="270" Title="!(loc.ExitDialog_Title)">
<Dialog Id="UI_AnotherAppDialog" Width="370" Height="270" Title="!(loc.ExitDialog_Title)">
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="EndDialog" Value="ErrorAbort" />
</Control>

View File

@ -0,0 +1,31 @@
<!-- https://github.com/wixtoolset/wix/blob/ce73352b1fa1d4f9cded10a0ee410f2e786bd326/src/ext/UI/wixlib/InstallDirDlg.wxs -->
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<UI>
<Dialog Id="MyInstallDirDlg" Width="370" Height="270" Title="!(loc.InstallDirDlg_Title)">
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg" />
</Control>
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.InstallDirDlgDescription)" />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.InstallDirDlgTitle)" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="FolderLabel" Type="Text" X="20" Y="60" Width="290" Height="18" NoPrefix="yes" Text="!(loc.InstallDirDlgFolderLabel)" />
<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)" />
</Dialog>
</UI>
</Fragment>
</Wix>

View File

@ -0,0 +1,87 @@
<!-- From https://github.com/wixtoolset/wix/blob/ce73352b1fa1d4f9cded10a0ee410f2e786bd326/src/ext/UI/wixlib/WixUI_InstallDir.wxs -->
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<!--
First-time install dialog sequence:
- WixUI_WelcomeDlg
- WixUI_LicenseAgreementDlg
- WixUI_InstallDirDlg
- WixUI_VerifyReadyDlg
- WixUI_DiskCostDlg
Maintenance dialog sequence:
- WixUI_MaintenanceWelcomeDlg
- WixUI_MaintenanceTypeDlg
- WixUI_InstallDirDlg
- WixUI_VerifyReadyDlg
Patch dialog sequence:
- WixUI_WelcomeDlg
- WixUI_VerifyReadyDlg
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
<?foreach WIXUIARCH in X86;X64;A64 ?>
<Fragment>
<UI Id="UI_MyInstallDialog_$(WIXUIARCH)">
<Publish Dialog="LicenseAgreementDlg" Control="Print" Event="DoAction" Value="WixUIPrintEula_$(WIXUIARCH)" />
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath_$(WIXUIARCH)" Order="3" Condition="NOT WIXUI_DONTVALIDATEPATH" />
<Publish Dialog="MyInstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath_$(WIXUIARCH)" Order="2" Condition="NOT WIXUI_DONTVALIDATEPATH" />
</UI>
<UIRef Id="UI_MyInstallDialog" />
</Fragment>
<?endforeach?>
<Fragment>
<UI Id="file UI_MyInstallDialog">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<DialogRef Id="BrowseDlg" />
<DialogRef Id="DiskCostDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4" Condition="NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID&lt;&gt;&quot;1&quot;" />
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999" />
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg" Condition="NOT Installed" />
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Condition="Installed AND PATCH" />
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" />
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="MyInstallDirDlg" Condition="LicenseAccepted = &quot;1&quot;" />
<Publish Dialog="MyInstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg" />
<Publish Dialog="MyInstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1" />
<Publish Dialog="MyInstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3" Condition="NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID&lt;&gt;&quot;1&quot;" />
<Publish Dialog="MyInstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4" Condition="WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=&quot;1&quot;" />
<Publish Dialog="MyInstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1" />
<Publish Dialog="MyInstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MyInstallDirDlg" Order="1" Condition="NOT Installed" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2" Condition="Installed AND NOT PATCH" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2" Condition="Installed AND PATCH" />
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg" />
<Property Id="ARPNOMODIFY" Value="1" />
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Wix>

View File

@ -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}<RegistryValue Type="string" Name="DisplayName" Value="{args.app_name}" />\n'
)
lines_new.append(
f'{indent}<RegistryValue Type="string" Name="DisplayIcon" Value="[INSTALLFOLDER]{args.app_name}.exe" />\n'
f'{indent}<RegistryValue Type="string" Name="DisplayIcon" Value="[INSTALLFOLDER_INNER]{args.app_name}.exe" />\n'
)
lines_new.append(
f'{indent}<RegistryValue Type="string" Name="DisplayVersion" Value="{g_version}" />\n'
@ -314,7 +314,7 @@ def gen_custom_ARPSYSTEMCOMPONENT_True(args, dist_dir):
f'{indent}<RegistryValue Type="string" Name="InstallDate" Value="{installDate}" />\n'
)
lines_new.append(
f'{indent}<RegistryValue Type="string" Name="InstallLocation" Value="[INSTALLFOLDER]" />\n'
f'{indent}<RegistryValue Type="string" Name="InstallLocation" Value="[INSTALLFOLDER_INNER]" />\n'
)
lines_new.append(
f'{indent}<RegistryValue Type="string" Name="InstallSource" Value="[InstallSource]" />\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()
# <Component Id="Product.Registry.DefaultIcon" Guid="6DBF2690-0955-4C6A-940F-634DDA503F49">
@ -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)