Skip to content

Commit

Permalink
Initial msi installer packaging (#127)
Browse files Browse the repository at this point in the history
* devolutions-gateway: begin msi installer

* devolutions-gateway: improve packaging

* devolutions-package: fix PowerShell module inclusion in installer

* devolutions-gateway: update Windows package resources

* devolutions-gateway: fix service uninstallation + icon in control panel

* devolutions-gateway: don't start service on installation, set to on-demand by default

Co-authored-by: Marc-André Moreau <mamoreau@devolutions.net>
  • Loading branch information
awakecoding and Marc-André Moreau authored Dec 11, 2020
1 parent 8ccc2b5 commit 04b1062
Show file tree
Hide file tree
Showing 14 changed files with 24,619 additions and 0 deletions.
10 changes: 10 additions & 0 deletions package/Windows/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
!*.sln
!WixUserPrivilegesExtension.dll
*.wixobj
*.wixpdb
*.mst
*.msi
*.zip
bin/
DevolutionsGateway/
DevolutionsGateway-x64.wxs
Binary file added package/Windows/DevolutionsGateway.ico
Binary file not shown.
238 changes: 238 additions & 0 deletions package/Windows/DevolutionsGateway.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="UTF-8"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:fw="http://schemas.microsoft.com/wix/FirewallExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:UserPrivileges="http://schemas.appsecinc.com/wix/UserPrivilegesExtension">

<?define VendorName = "Devolutions" ?>
<?define ProductName = "Devolutions Gateway" ?>
<?define ServiceName = "DevolutionsGateway" ?>
<?define ServiceDisplayName = "Devolutions Gateway Service" ?>
<?define ServiceDescription = "Devolutions Gateway Service" ?>

<!-- Upgrade code HAS to be the same for all updates. Once you've chosen it don't change it. -->
<?define UpgradeCode="db3903d6-c451-4393-bd80-eb9f45b90214" ?>

<!-- The URL for add/remove programs -->
<?define InfoURL="https://wayk.devolutions.net" ?>

<!-- SDDL string representing desired %programdata%\wayk ACL -->
<!-- SYSTEM/BuiltInAdministrators = Full Control, BuiltInUsers - Read/Execute -->
<?define ProgramDataSddl="D:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)" ?>

<!-- 32-bit / 64-bit variables -->
<?if $(var.Platform) = x64 ?>
<?define Win64 = "yes" ?>
<?define ProcessorBits = "64" ?>
<?define ProcessorArchitecture = "x64" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else ?>
<?define Win64 = "no" ?>
<?define ProcessorBits = "32" ?>
<?define ProcessorArchitecture = "x86" ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?endif ?>

<!--
====================================================================================
Package start
-->

<!-- The upgrade code must never change as long as the product lives! -->
<!-- Product IDs must be autogenerated (*) or else major upgrades will not work -->
<Product Id="*" Name="$(var.ProductName)" Language="!(loc.Language)" Version="$(var.Version)" Manufacturer="!(loc.VendorFullName)" UpgradeCode="$(var.UpgradeCode)">

<!-- Package IDs are valid for a single package version only - they are autogenerated by WiX -->
<!-- Let's require Windows Installer 4.0 (included in Vista) -->
<!-- And ALWAYS install per machine!!! -->
<Package Id="*" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated" Description="!(loc.ProductDescription)" Platform="$(var.Platform)" Languages="!(loc.Language)"/>

<!-- License agreement text: dummy. Real text is set in WXS file -->
<WixVariable Id="WixUILicenseRtf" Value="$(var.WixUILicenseRtf)" />

<!-- UI customization -->
<WixVariable Id="WixUIBannerBmp" Value="WixUIBanner.jpg" />
<WixVariable Id="WixUIDialogBmp" Value="WixUiDialog.jpg" />

<!-- Define icons (ID should not be longer than 18 chars and must end with ".exe") -->
<Icon Id="DevolutionsGateway.ico" SourceFile="DevolutionsGateway.ico" />

<!-- Helper properties for determining what action is taking place -->
<SetProperty After="FindRelatedProducts" Id="FirstInstall" Value="true">
NOT Installed AND NOT WIX_UPGRADE_DETECTED AND NOT WIX_DOWNGRADE_DETECTED
</SetProperty>
<SetProperty After="SetFirstInstall" Id="Upgrading" Value="true">
WIX_UPGRADE_DETECTED AND NOT (REMOVE="ALL")
</SetProperty>
<SetProperty After="RemoveExistingProducts" Id="RemovingForUpgrade" Sequence="execute" Value="true">
(REMOVE="ALL") AND UPGRADINGPRODUCTCODE
</SetProperty>
<SetProperty After="SetUpgrading" Id="Uninstalling" Value="true">
Installed AND REMOVE AND NOT (WIX_UPGRADE_DETECTED OR UPGRADINGPRODUCTCODE)
</SetProperty>
<SetProperty After="SetUninstalling" Id="Maintenance" Value="true">
Installed AND NOT Upgrading AND NOT Uninstalling AND NOT UPGRADINGPRODUCTCODE
</SetProperty>

<!-- Disable the restart manager, it prompts unnecessarily for subprocesses -->
<Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable"/>

<!-- Set properties for add/remove programs -->
<Property Id="ARPPRODUCTICON" Value="DevolutionsGateway.ico" />
<Property Id="ARPHELPLINK" Value="$(var.InfoURL)" />

<!-- Clear this property to auto launch executable after installation -->
<Property Id="SUPPRESSLAUNCH" Value="1" />

<Property Id="INSTALLDESKTOPSHORTCUT" Value="0" />
<Property Id="INSTALLSTARTMENUSHORTCUT" Value="0" />

<!-- Upgrade logic -->
<!-- AllowSameVersionUpgrades -> Always upgrade, never allow two versions to be installed next to each other -->
<!-- AllowSameVersionUpgrades causes ICE61 which must be ignored -->
<MajorUpgrade DowngradeErrorMessage="!(loc.NewerInstalled)" AllowSameVersionUpgrades="yes" />

<!-- This is the main installer sequence run when the product is actually installed -->
<InstallExecuteSequence>
<!-- Force permissions on %ProgramData%\Devolutions\Gateway -->
<Custom Action='Set_ProgramDataPermissions' After='CreateFolders'/>

<!-- Determine the install location after the install path has been validated by the installer -->
<Custom Action="SetARPINSTALLLOCATION" After="InstallValidate"/>

<Custom Action="SetREINSTALL" Before="CostInitialize">
Maintenance AND NOT REINSTALL
</Custom>
</InstallExecuteSequence>

<!-- Reinstall the DGatewayService feature on maintenance installations
This forces the service to be stopped and started,
re-reading any configuration updated by the installer-->
<CustomAction Id="SetREINSTALL" Property="REINSTALL" Value="DGatewayService" />

<!-- Set up ARPINSTALLLOCATION property (http://blogs.technet.com/b/alexshev/archive/2008/02/09/from-msi-to-wix-part-2.aspx) -->
<CustomAction Id="SetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />

<Property Id="Set_ProgramDataPermissions" Value='"cmd.exe" /c ECHO Y| &quot;%windir%\System32\cacls.exe&quot; %ProgramData%\Devolutions\Gateway /S:$(var.ProgramDataSddl) /C' />
<CustomAction Id="Set_ProgramDataPermissions" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Impersonate="no" Return="ignore"/>

<!--
Launch conditions
-->
<Condition Message="!(loc.OS2Old)">
<![CDATA[Installed OR (VersionNT >= 601)]]>
</Condition>

<?if $(var.Platform) = x64 ?>
<Condition Message="!(loc.x86VersionRequired)">
<![CDATA[VersionNT64]]>
</Condition>
<?endif?>
<?if $(var.Platform) = x86 ?>
<Condition Message="!(loc.x64VersionRequired)">
<![CDATA[NOT VersionNT64]]>
</Condition>
<?endif?>

<!--
Launch conditions end
-->

<!-- Determine the directory of a previous installation (if one exists). If not INSTALLDIR stays empty -->
<Property Id="INSTALLDIR">
<RegistrySearch Id="DetermineInstallLocation" Type="raw" Root="HKLM" Key="Software\$(var.VendorName)\InstalledProducts\$(var.ProductName)" Name="InstallLocation" />
</Property>

<!--
====================================================================================
Start to build directory structure
-->
<!-- We do not have more than one medium (Floppy, CD, ...). Everything in one file. -->
<Media Id="1" Cabinet="dgateway.cab" EmbedCab="yes" />

<!-- Outermost folder (kind of virtual). Fixed entry. -->
<Directory Id="TARGETDIR" Name="SourceDir">

<!-- We start building our directory structure here -->
<!-- "ProgramFilesFolder" is a variable containing the absolute path. -->
<!-- For a list of folder variables, see: http://msdn.microsoft.com/en-us/library/aa372057%28VS.85%29.aspx -->
<Directory Id="$(var.PlatformProgramFilesFolder)" Name="PFiles">

<!-- All folders from here on are relative to their parent. -->

<Directory Id="APPLICATIONFOLDER" Name="$(var.VendorName)">

<!-- INSTALLDIR is a property name. We need it later for the UI (to be able to change the install dir. -->
<Directory Id="INSTALLDIR" Name="Gateway">

<Directory Id="PowerShell" Name="PowerShell">
<Directory Id="Modules" Name="Modules">
<Directory Id="DGATEWAYPSROOTDIRECTORY" Name="DevolutionsGateway"/>
</Directory>
</Directory>

<Component Id="cmpDGatewayRegistryEntries" Guid="*" Win64="$(var.Win64)">
<RegistryKey Root="HKLM" Key="Software\Devolutions\Gateway">
<RegistryValue Type="string" Name="InstallDir" Value="[INSTALLDIR]" KeyPath="yes"/>
</RegistryKey>

</Component>
</Directory>
</Directory>
</Directory>

<Directory Id="CommonAppDataFolder">
<Directory Id="CommonDevolutionsFolder" Name="Devolutions">
<Directory Id="ProgramDataFolder" Name="Gateway">
</Directory>
</Directory>
</Directory>
</Directory>

<DirectoryRef Id="ProgramDataFolder">
<Component Id="cmpCommonAppDataFolder" Guid="dc6b6f37-78d2-4f0a-9464-d1f63ef64fab" Permanent="yes">
<CreateFolder>
<PermissionEx Sddl="$(var.ProgramDataSddl)" />
</CreateFolder>
</Component>
</DirectoryRef>

<Component Id="cmpDGatewayService" Guid="31eaa967-64e3-469c-b0c9-c9ecea61b7d3" Win64="$(var.Win64)" Directory="INSTALLDIR">
<File Name="DevolutionsGateway.exe" Source="./bin/$(var.ProcessorArchitecture)/DevolutionsGateway.exe" Id="DevolutionsGateway.exe" ProcessorArchitecture="$(var.ProcessorArchitecture)" KeyPath="yes" Vital="yes" DiskId="1">
<fw:FirewallException Id="DGatewayServiceFirewallExceptionTcp" Name="Wayk Now Service TCP" Description="Wayk Now Service TCP" Protocol="tcp" Profile="all" Scope="any" IgnoreFailure="yes"/>
<fw:FirewallException Id="DGatewayServiceFirewallExceptionUdp" Name="Wayk Now Service UDP" Description="Wayk Now Service UDP" Protocol="udp" Profile="all" Scope="any" IgnoreFailure="yes"/>
</File>
<ServiceInstall Id="DGatewayServiceControl" Type="ownProcess" Interactive="no" Vital="yes" Name="$(var.ServiceName)" Arguments="--service"
DisplayName="$(var.ServiceDisplayName)" Description="$(var.ServiceDescription)" Start="demand" ErrorControl="ignore">
<util:ServiceConfig FirstFailureActionType='restart' SecondFailureActionType='restart' ThirdFailureActionType='restart' RestartServiceDelayInSeconds='900' ResetPeriodInDays='1'/>
</ServiceInstall>
<ServiceControl Id="DGatewayServiceControl" Stop="both" Remove="uninstall" Name="$(var.ServiceName)" Wait="no" />
</Component>

<!--
End of directory structure
====================================================================================
-->

<!-- Features define which parts of the application can be installed in a custom installation -->
<Feature Id="DGatewayService" Title="$(var.ServiceDisplayName)" Display="expand" Level="1" Absent="disallow" AllowAdvertise="no">
<ComponentRef Id="cmpDGatewayService"/>
<ComponentRef Id="cmpCommonAppDataFolder"/>
<ComponentRef Id="cmpDGatewayRegistryEntries"/>
<ComponentGroupRef Id="DGatewayPSComponentGroup"/>
</Feature>

<UI Id="MyWixUI_InstallDir">
<UIRef Id="WixUI_InstallDir"/>
</UI>

<UI>
<TextStyle Id="MyWixUI_Font_Title" FaceName="!(loc.Advanced_Font_FaceName)" Size="!(loc.Advanced_Font_Title_Size)" Bold="yes" Red="255" Blue="255" Green="255" />
<TextStyle Id="MyWixUI_Font_Description" FaceName="!(loc.Advanced_Font_FaceName)" Size="!(loc.Advanced_Font_Normal_Size)" Red="255" Blue="255" Green="255" />
</UI>

<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
</Product>

</Wix>
Loading

0 comments on commit 04b1062

Please sign in to comment.