mirror of
https://github.com/zellij-org/zellij.git
synced 2026-10-11 22:50:07 +00:00
Add Windows MSI installer with WiX v6 (#4847)
* Add Windows MSI installer with WiX v6 Build a dual-scope MSI installer that lets users choose per-user (%LocalAppData%\Zellij) or per-machine (Program Files\Zellij) install, with automatic PATH configuration and clean uninstall support. - Custom UI based on stock WixToolset.UI.wixext dialogs to work around the long-standing WixUI_Advanced dual-scope bug (wixtoolset/issues#7137) - Custom folder resolution CAs (SetFolderPerUser/SetFolderPerMachine) - Embed application icon into zellij.exe via embed-resource - Icon shown in Add/Remove Programs via ARPPRODUCTICON - MSI build integrated into release.yml CI workflow * Add MSI installer to no-web build and fix artifact naming - Add MSI build steps to build-release-noweb job - Add SHA256 checksums for MSI artifacts - Pin WixToolset.UI.wixext to 6.0.2 to avoid v7 RC incompatibility - Use -installer suffix after target in artifact names --------- Co-authored-by: divens <[email protected]>
This commit is contained in:
@@ -162,6 +162,57 @@ jobs:
|
||||
asset_name: zellij-${{matrix.target}}.sha256sum
|
||||
asset_content_type: text/plain
|
||||
|
||||
# ===== Windows MSI installer =====
|
||||
- name: Install WiX v6
|
||||
if: runner.os == 'Windows'
|
||||
run: dotnet tool install --global wix
|
||||
|
||||
- name: Add WiX UI extension
|
||||
if: runner.os == 'Windows'
|
||||
run: wix extension add WixToolset.UI.wixext/6.0.2
|
||||
|
||||
- name: Build MSI installer
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
$version = (Select-String -Path Cargo.toml -Pattern '^version\s*=\s*"(.+)"' | Select-Object -First 1).Matches.Groups[1].Value
|
||||
New-Item -ItemType Directory -Force -Path target\wix
|
||||
wix build wix\main.wxs wix\Zellij.wxl `
|
||||
-d Version=$version `
|
||||
-arch x64 `
|
||||
-ext WixToolset.UI.wixext `
|
||||
-o target\wix\zellij-x86_64-pc-windows-msvc-installer.msi
|
||||
|
||||
- name: Create MSI checksum
|
||||
if: runner.os == 'Windows'
|
||||
id: make-checksum-msi
|
||||
run: |
|
||||
$checksum_name = "zellij-${{ matrix.target }}-installer.sha256sum"
|
||||
$hash = (Get-FileHash "target\wix\zellij-${{ matrix.target }}-installer.msi" -Algorithm SHA256).Hash.ToLower()
|
||||
"$hash zellij-${{ matrix.target }}-installer.msi" | Out-File -Encoding ascii $checksum_name
|
||||
echo "checksum_name=$checksum_name" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Upload MSI installer
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/[email protected]
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||
asset_path: target\wix\zellij-${{ matrix.target }}-installer.msi
|
||||
asset_name: zellij-${{ matrix.target }}-installer.msi
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload MSI checksum
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/[email protected]
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||
asset_path: ${{ steps.make-checksum-msi.outputs.checksum_name }}
|
||||
asset_name: zellij-${{ matrix.target }}-installer.sha256sum
|
||||
asset_content_type: text/plain
|
||||
|
||||
build-release-noweb:
|
||||
needs: create-release
|
||||
name: build-release-noweb
|
||||
@@ -301,3 +352,54 @@ jobs:
|
||||
asset_path: ${{ steps.make-checksum-unix.outputs.checksum_name || steps.make-checksum-windows.outputs.checksum_name }}
|
||||
asset_name: zellij-no-web-${{matrix.target}}.sha256sum
|
||||
asset_content_type: text/plain
|
||||
|
||||
# ===== Windows MSI installer (no-web) =====
|
||||
- name: Install WiX v6
|
||||
if: runner.os == 'Windows'
|
||||
run: dotnet tool install --global wix
|
||||
|
||||
- name: Add WiX UI extension
|
||||
if: runner.os == 'Windows'
|
||||
run: wix extension add WixToolset.UI.wixext/6.0.2
|
||||
|
||||
- name: Build MSI installer (no-web)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
$version = (Select-String -Path Cargo.toml -Pattern '^version\s*=\s*"(.+)"' | Select-Object -First 1).Matches.Groups[1].Value
|
||||
New-Item -ItemType Directory -Force -Path target\wix
|
||||
wix build wix\main.wxs wix\Zellij.wxl `
|
||||
-d Version=$version `
|
||||
-arch x64 `
|
||||
-ext WixToolset.UI.wixext `
|
||||
-o target\wix\zellij-no-web-${{ matrix.target }}-installer.msi
|
||||
|
||||
- name: Create MSI checksum (no-web)
|
||||
if: runner.os == 'Windows'
|
||||
id: make-checksum-msi
|
||||
run: |
|
||||
$checksum_name = "zellij-no-web-${{ matrix.target }}-installer.sha256sum"
|
||||
$hash = (Get-FileHash "target\wix\zellij-no-web-${{ matrix.target }}-installer.msi" -Algorithm SHA256).Hash.ToLower()
|
||||
"$hash zellij-no-web-${{ matrix.target }}-installer.msi" | Out-File -Encoding ascii $checksum_name
|
||||
echo "checksum_name=$checksum_name" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Upload MSI installer (no-web)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/[email protected]
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||
asset_path: target\wix\zellij-no-web-${{ matrix.target }}-installer.msi
|
||||
asset_name: zellij-no-web-${{ matrix.target }}-installer.msi
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload MSI checksum (no-web)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/[email protected]
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||
asset_path: ${{ steps.make-checksum-msi.outputs.checksum_name }}
|
||||
asset_name: zellij-no-web-${{ matrix.target }}-installer.sha256sum
|
||||
asset_content_type: text/plain
|
||||
|
||||
Generated
+130
-6
@@ -965,6 +965,20 @@ version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "embed-resource"
|
||||
version = "3.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"memchr",
|
||||
"rustc_version",
|
||||
"toml 0.9.6",
|
||||
"vswhom",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
@@ -2908,6 +2922,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver 1.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.28"
|
||||
@@ -3085,6 +3108,12 @@ dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.10.2"
|
||||
@@ -3096,18 +3125,28 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3136,6 +3175,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
@@ -3838,6 +3886,45 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae2a4cf385da23d1d53bc15cdfa5c2109e93d8d362393c801e87da2f72f0e201"
|
||||
dependencies = [
|
||||
"indexmap 2.7.1",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"toml_writer",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.5+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.9+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.2"
|
||||
@@ -4086,6 +4173,26 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "vswhom"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"vswhom-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vswhom-sys"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vte"
|
||||
version = "0.10.1"
|
||||
@@ -4655,6 +4762,22 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.55.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winx"
|
||||
version = "0.36.3"
|
||||
@@ -4729,7 +4852,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"prost-build",
|
||||
"serde_json",
|
||||
"toml",
|
||||
"toml 0.5.10",
|
||||
"which",
|
||||
"xflags",
|
||||
"xshell",
|
||||
@@ -4774,6 +4897,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"dialoguer",
|
||||
"embed-resource",
|
||||
"humantime",
|
||||
"insta",
|
||||
"interprocess",
|
||||
@@ -4865,7 +4989,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"prost",
|
||||
"regex",
|
||||
"semver",
|
||||
"semver 0.11.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signal-hook",
|
||||
|
||||
@@ -33,6 +33,9 @@ isahc = { workspace = true }
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { workspace = true }
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
embed-resource = "3"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.6.0", features = ["backtrace"] }
|
||||
ssh2 = "0.9.1"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1 @@
|
||||
1 ICON "assets\\logo128.ico"
|
||||
@@ -6,4 +6,8 @@ fn main() {
|
||||
if cfg!(target_os = "windows") && std::env::var("PROFILE").unwrap_or_default() != "release" {
|
||||
println!("cargo:rustc-link-arg=/STACK:8388608");
|
||||
}
|
||||
|
||||
// Embed the application icon into the Windows executable.
|
||||
#[cfg(target_os = "windows")]
|
||||
embed_resource::compile("assets/zellij.rc", embed_resource::NONE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{\rtf1\ansi\deff0
|
||||
{\fonttbl{\f0\fswiss Segoe UI;}}
|
||||
\viewkind4\uc1
|
||||
\pard\f0\fs20
|
||||
|
||||
\b MIT License\b0\par
|
||||
\par
|
||||
Copyright (c) 2020 Zellij contributors\par
|
||||
\par
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \ldblquote Software\rdblquote ), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\par
|
||||
\par
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\par
|
||||
\par
|
||||
THE SOFTWARE IS PROVIDED \ldblquote AS IS\rdblquote , WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\par
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
|
||||
<String Id="AdvancedWelcomeEulaDlgDescriptionPerMachine" Value="Click Install to install Zellij for all users. Click Advanced to choose install scope and directory." />
|
||||
<String Id="AdvancedWelcomeEulaDlgDescriptionPerUser" Value="Click Install to install Zellij just for you. Click Advanced to choose install scope and directory." />
|
||||
</WixLocalization>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 451 KiB |
+347
@@ -0,0 +1,347 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Zellij MSI installer (WiX v6).
|
||||
|
||||
Custom UI built from individual WixToolset.UI.wixext stock dialogs plus a
|
||||
custom welcome/EULA dialog (ZellijWelcomeDlg). We do NOT use the stock
|
||||
WixUI_Advanced dialog set because:
|
||||
- It does not support dual-scope packages (wixtoolset/issues#7137)
|
||||
- Its AdvancedWelcomeEulaDlg cannot be overridden (not declared virtual)
|
||||
- It includes a Print button and FeaturesDlg we don't need
|
||||
|
||||
Instead we reference stock dialogs individually (InstallScopeDlg,
|
||||
InstallDirDlg, VerifyReadyDlg, etc.) and wire up navigation ourselves.
|
||||
|
||||
Dual-scope support:
|
||||
Scope="perUserOrMachine" sets ALLUSERS=2, MSIINSTALLPERUSER=1.
|
||||
Custom actions (SetFolderPerUser / SetFolderPerMachine) resolve
|
||||
APPLICATIONFOLDER to the correct path based on scope selection.
|
||||
The stock WixUI_Advanced folder CAs are broken for this scenario.
|
||||
|
||||
Dialog flow:
|
||||
New install: ZellijWelcomeDlg → [Advanced] → InstallScopeDlg
|
||||
→ InstallDirDlg → VerifyReadyDlg
|
||||
Quick install: ZellijWelcomeDlg → [Install] (per-user, no UAC)
|
||||
Maintenance: MaintenanceWelcomeDlg → MaintenanceTypeDlg → VerifyReadyDlg
|
||||
|
||||
Build:
|
||||
wix build wix\main.wxs wix\Zellij.wxl -d Version=X.Y.Z -arch x64
|
||||
-ext WixToolset.UI.wixext -o target\wix\zellij-x86_64-pc-windows-msvc.msi
|
||||
-->
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
|
||||
<Package Name="Zellij"
|
||||
Manufacturer="Zellij Contributors"
|
||||
Version="$(var.Version)"
|
||||
UpgradeCode="BEE7A897-6DE0-4243-9977-5924C8CDB391"
|
||||
Scope="perUserOrMachine"
|
||||
InstallerVersion="500">
|
||||
|
||||
<!-- Properties used by stock InstallScopeDlg and InstallDirDlg -->
|
||||
<Property Id="ApplicationFolderName" Value="Zellij" />
|
||||
<Property Id="WixAppFolder" Value="WixPerUserFolder" />
|
||||
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER" />
|
||||
|
||||
<!-- Icon shown in Add/Remove Programs -->
|
||||
<Icon Id="ZellijIcon" SourceFile="assets\logo128.ico" />
|
||||
<Property Id="ARPPRODUCTICON" Value="ZellijIcon" />
|
||||
|
||||
<!-- Auto-remove previous versions -->
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of Zellij is already installed." />
|
||||
|
||||
<!-- Embed the .cab inside the MSI -->
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<!-- ===== Directory tree ===== -->
|
||||
<StandardDirectory Id="ProgramFilesFolder">
|
||||
<Directory Id="APPLICATIONFOLDER" Name="Zellij" />
|
||||
</StandardDirectory>
|
||||
|
||||
<!-- ===== Custom actions for folder resolution =====
|
||||
The stock WixUI_Advanced CAs (WixSetPerUserFolder / WixSetPerMachineFolder)
|
||||
resolve incorrectly under Scope="perUserOrMachine" because WixPerMachineFolder
|
||||
is evaluated before the user selects a scope. We bypass them entirely and set
|
||||
APPLICATIONFOLDER to explicit paths based on MSIINSTALLPERUSER. -->
|
||||
<CustomAction Id="SetFolderPerUser"
|
||||
Property="APPLICATIONFOLDER"
|
||||
Value="[LocalAppDataFolder]Zellij" />
|
||||
<CustomAction Id="SetFolderPerMachine"
|
||||
Property="APPLICATIONFOLDER"
|
||||
Value="[ProgramFilesFolder]Zellij" />
|
||||
|
||||
<!-- Schedule in both UI and Execute sequences so the correct path is set
|
||||
even after UAC elevation re-launches the server process. -->
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="SetFolderPerUser" Before="CostFinalize"
|
||||
Condition="MSIINSTALLPERUSER = 1" />
|
||||
<Custom Action="SetFolderPerMachine" Before="CostFinalize"
|
||||
Condition="NOT MSIINSTALLPERUSER" />
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<InstallUISequence>
|
||||
<Custom Action="SetFolderPerUser" Before="CostFinalize"
|
||||
Condition="MSIINSTALLPERUSER = 1" />
|
||||
<Custom Action="SetFolderPerMachine" Before="CostFinalize"
|
||||
Condition="NOT MSIINSTALLPERUSER" />
|
||||
</InstallUISequence>
|
||||
|
||||
<!-- ===== Components =====
|
||||
Three components: binary (always), plus two conditional PATH components.
|
||||
ALLUSERS is set by InstallScopeDlg: 1 for per-machine, empty for per-user.
|
||||
Default (quick install without scope dialog): ALLUSERS=2, which is <> 1,
|
||||
so path_user activates — correct for the per-user default. -->
|
||||
|
||||
<Component Id="binary"
|
||||
Directory="APPLICATIONFOLDER"
|
||||
Guid="BC9D18AE-17CA-4790-ADB0-C64530DEDE57">
|
||||
<File Id="zellij_exe"
|
||||
Source="target\release\zellij.exe"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<Component Id="path_machine"
|
||||
Directory="APPLICATIONFOLDER"
|
||||
Guid="85C2CC85-8379-4C27-8337-A90EAD9AC265"
|
||||
Condition="ALLUSERS = 1">
|
||||
<RegistryValue Root="HKLM"
|
||||
Key="Software\Zellij"
|
||||
Name="InstallPath"
|
||||
Type="string"
|
||||
Value="[APPLICATIONFOLDER]"
|
||||
KeyPath="yes" />
|
||||
<Environment Id="PATH_machine"
|
||||
Name="PATH"
|
||||
Value="[APPLICATIONFOLDER]"
|
||||
Permanent="no"
|
||||
Part="last"
|
||||
Action="set"
|
||||
System="yes" />
|
||||
</Component>
|
||||
|
||||
<Component Id="path_user"
|
||||
Directory="APPLICATIONFOLDER"
|
||||
Guid="EED3D01E-8FBC-4F3D-A3E5-DF55939970CD"
|
||||
Condition="ALLUSERS <> 1">
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\Zellij"
|
||||
Name="InstallPath"
|
||||
Type="string"
|
||||
Value="[APPLICATIONFOLDER]"
|
||||
KeyPath="yes" />
|
||||
<Environment Id="PATH_user"
|
||||
Name="PATH"
|
||||
Value="[APPLICATIONFOLDER]"
|
||||
Permanent="no"
|
||||
Part="last"
|
||||
Action="set"
|
||||
System="no" />
|
||||
</Component>
|
||||
|
||||
<!-- ===== Feature ===== -->
|
||||
<Feature Id="MainFeature" Title="Zellij" Level="1">
|
||||
<ComponentRef Id="binary" />
|
||||
<ComponentRef Id="path_machine" />
|
||||
<ComponentRef Id="path_user" />
|
||||
</Feature>
|
||||
|
||||
<!-- ===== Custom UI =====
|
||||
We define our own UI element instead of using <ui:WixUI Id="WixUI_Advanced" />
|
||||
because WiX v6 does not allow overriding extension dialogs (they are not
|
||||
declared virtual). We reference individual stock dialogs from
|
||||
WixToolset.UI.wixext and provide our own ZellijWelcomeDlg and navigation. -->
|
||||
<UI>
|
||||
<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" />
|
||||
<TextStyle Id="WixUI_Font_Emphasized" FaceName="Tahoma" Size="9" Bold="yes" />
|
||||
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
|
||||
|
||||
<!-- Individual stock dialogs from WixToolset.UI.wixext -->
|
||||
<DialogRef Id="BrowseDlg" />
|
||||
<DialogRef Id="DiskCostDlg" />
|
||||
<DialogRef Id="ErrorDlg" />
|
||||
<DialogRef Id="ExitDialog" />
|
||||
<DialogRef Id="FatalError" />
|
||||
<DialogRef Id="FilesInUse" />
|
||||
<DialogRef Id="InstallDirDlg" />
|
||||
<DialogRef Id="InstallScopeDlg" />
|
||||
<DialogRef Id="MaintenanceTypeDlg" />
|
||||
<DialogRef Id="MaintenanceWelcomeDlg" />
|
||||
<DialogRef Id="MsiRMFilesInUse" />
|
||||
<DialogRef Id="PrepareDlg" />
|
||||
<DialogRef Id="ProgressDlg" />
|
||||
<DialogRef Id="ResumeDlg" />
|
||||
<DialogRef Id="UserExit" />
|
||||
<DialogRef Id="VerifyReadyDlg" />
|
||||
<DialogRef Id="WaitForCostingDlg" />
|
||||
|
||||
<!-- ==========================================
|
||||
ZellijWelcomeDlg — custom welcome + EULA dialog.
|
||||
Based on the stock AdvancedWelcomeEulaDlg from WixToolset.UI.wixext
|
||||
(src/ext/UI/wixlib/AdvancedWelcomeEulaDlg.wxs) with Print button removed.
|
||||
Localization strings (!(loc.XXX)) come from the extension's WXL files;
|
||||
overrides are in wix/Zellij.wxl.
|
||||
========================================== -->
|
||||
<Dialog Id="ZellijWelcomeDlg" Width="370" Height="270"
|
||||
Title="!(loc.AdvancedWelcomeEulaDlg_Title)">
|
||||
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44"
|
||||
TabSkip="no" Text="!(loc.AdvancedWelcomeEulaDlgBannerBitmap)" />
|
||||
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="373" Height="0" />
|
||||
<Control Id="Title" Type="Text" X="20" Y="10" Width="300" Height="24"
|
||||
Transparent="yes" NoPrefix="yes"
|
||||
Text="!(loc.AdvancedWelcomeEulaDlgTitle)" />
|
||||
<Control Id="DescriptionPerMachine" Type="Text" X="20" Y="202" Width="330" Height="31"
|
||||
Transparent="yes" NoPrefix="yes" Hidden="yes"
|
||||
Text="!(loc.AdvancedWelcomeEulaDlgDescriptionPerMachine)"
|
||||
ShowCondition="ALLUSERS" />
|
||||
<Control Id="DescriptionPerUser" Type="Text" X="20" Y="202" Width="330" Height="31"
|
||||
Transparent="yes" NoPrefix="yes" Hidden="yes"
|
||||
Text="!(loc.AdvancedWelcomeEulaDlgDescriptionPerUser)"
|
||||
ShowCondition="NOT ALLUSERS" />
|
||||
<Control Id="LicenseAcceptedCheckBox" Type="CheckBox" X="20" Y="180" Width="226" Height="18"
|
||||
CheckBoxValue="1" Property="LicenseAccepted"
|
||||
Text="!(loc.WelcomeEulaDlgLicenseAcceptedCheckBox)" />
|
||||
<Control Id="LicenseText" Type="ScrollableText" X="20" Y="55" Width="330" Height="121"
|
||||
Sunken="yes" TabSkip="no">
|
||||
<Text SourceFile="!(wix.WixUILicenseRtf)" />
|
||||
</Control>
|
||||
<Control Id="Advanced" Type="PushButton" X="156" Y="243" Width="56" Height="17"
|
||||
Text="!(loc.AdvancedWelcomeEulaDlgAdvanced)"
|
||||
DisableCondition="LicenseAccepted <> "1""
|
||||
EnableCondition="LicenseAccepted = "1"" />
|
||||
<Control Id="Install" Type="PushButton" ElevationShield="yes"
|
||||
X="212" Y="243" Width="80" Height="17" Default="yes"
|
||||
Text="!(loc.AdvancedWelcomeEulaDlgInstall)" Hidden="yes"
|
||||
DisableCondition="LicenseAccepted <> "1""
|
||||
EnableCondition="LicenseAccepted = "1""
|
||||
ShowCondition="ALLUSERS">
|
||||
<Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg"
|
||||
Condition="!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1" />
|
||||
<Publish Event="EndDialog" Value="Return"
|
||||
Condition="OutOfDiskSpace <> 1" />
|
||||
<Publish Event="SpawnDialog" Value="OutOfRbDiskDlg"
|
||||
Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)" />
|
||||
<Publish Event="EndDialog" Value="Return"
|
||||
Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"" />
|
||||
<Publish Event="EnableRollback" Value="False"
|
||||
Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"" />
|
||||
<Publish Event="SpawnDialog" Value="OutOfDiskDlg"
|
||||
Condition="(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")" />
|
||||
</Control>
|
||||
<Control Id="InstallNoShield" Type="PushButton" ElevationShield="no"
|
||||
X="212" Y="243" Width="80" Height="17" Default="yes"
|
||||
Text="!(loc.AdvancedWelcomeEulaDlgInstall)" Hidden="yes"
|
||||
DisableCondition="LicenseAccepted <> "1""
|
||||
EnableCondition="LicenseAccepted = "1""
|
||||
ShowCondition="NOT ALLUSERS">
|
||||
<Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg"
|
||||
Condition="!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1" />
|
||||
<Publish Event="EndDialog" Value="Return"
|
||||
Condition="OutOfDiskSpace <> 1" />
|
||||
<Publish Event="SpawnDialog" Value="OutOfRbDiskDlg"
|
||||
Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)" />
|
||||
<Publish Event="EndDialog" Value="Return"
|
||||
Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"" />
|
||||
<Publish Event="EnableRollback" Value="False"
|
||||
Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"" />
|
||||
<Publish Event="SpawnDialog" Value="OutOfDiskDlg"
|
||||
Condition="(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")" />
|
||||
</Control>
|
||||
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17"
|
||||
Cancel="yes" Text="!(loc.WixUICancel)">
|
||||
<Publish Event="SpawnDialog" Value="CancelDlg" />
|
||||
</Control>
|
||||
</Dialog>
|
||||
|
||||
<!-- ==========================================
|
||||
Navigation: new install flow.
|
||||
Scope dialog sets ALLUSERS, MSIINSTALLPERUSER, and fires our
|
||||
folder CAs so InstallDirDlg shows the correct default path.
|
||||
========================================== -->
|
||||
<Publish Dialog="ZellijWelcomeDlg" Control="Advanced"
|
||||
Event="NewDialog" Value="InstallScopeDlg" />
|
||||
|
||||
<Publish Dialog="InstallScopeDlg" Control="Back"
|
||||
Event="NewDialog" Value="ZellijWelcomeDlg" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Property="WixAppFolder" Value="WixPerUserFolder" Order="1"
|
||||
Condition="NOT Privileged" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Property="ALLUSERS" Value="{}" Order="2"
|
||||
Condition="WixAppFolder = "WixPerUserFolder"" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Property="ALLUSERS" Value="1" Order="3"
|
||||
Condition="WixAppFolder = "WixPerMachineFolder"" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Property="MSIINSTALLPERUSER" Value="1" Order="4"
|
||||
Condition="WixAppFolder = "WixPerUserFolder"" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Property="MSIINSTALLPERUSER" Value="{}" Order="5"
|
||||
Condition="WixAppFolder = "WixPerMachineFolder"" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Event="DoAction" Value="SetFolderPerUser" Order="6"
|
||||
Condition="WixAppFolder = "WixPerUserFolder"" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Event="DoAction" Value="SetFolderPerMachine" Order="7"
|
||||
Condition="WixAppFolder = "WixPerMachineFolder"" />
|
||||
<Publish Dialog="InstallScopeDlg" Control="Next"
|
||||
Event="NewDialog" Value="InstallDirDlg" Order="8" />
|
||||
|
||||
<Publish Dialog="InstallDirDlg" Control="Back"
|
||||
Event="NewDialog" Value="InstallScopeDlg" />
|
||||
<Publish Dialog="InstallDirDlg" Control="Next"
|
||||
Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1" />
|
||||
<Publish Dialog="InstallDirDlg" Control="Next"
|
||||
Event="NewDialog" Value="VerifyReadyDlg" Order="2" />
|
||||
<Publish Dialog="InstallDirDlg" Control="ChangeFolder"
|
||||
Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1" />
|
||||
<Publish Dialog="InstallDirDlg" Control="ChangeFolder"
|
||||
Event="SpawnDialog" Value="BrowseDlg" Order="2" />
|
||||
|
||||
<Publish Dialog="BrowseDlg" Control="OK"
|
||||
Event="SetTargetPath" Value="[_BrowseProperty]" Order="1" />
|
||||
<Publish Dialog="BrowseDlg" Control="OK"
|
||||
Event="EndDialog" Value="Return" Order="2" />
|
||||
|
||||
<Publish Dialog="VerifyReadyDlg" Control="Back"
|
||||
Event="NewDialog" Value="InstallDirDlg" Order="1"
|
||||
Condition="NOT Installed" />
|
||||
<Publish Dialog="VerifyReadyDlg" Control="Back"
|
||||
Event="NewDialog" Value="MaintenanceTypeDlg" Order="2"
|
||||
Condition="Installed AND NOT PATCH" />
|
||||
|
||||
<Publish Dialog="ExitDialog" Control="Finish"
|
||||
Event="EndDialog" Value="Return" Order="999" />
|
||||
|
||||
<!-- Navigation: maintenance (repair/uninstall) -->
|
||||
<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" />
|
||||
</UI>
|
||||
|
||||
<!-- Show our welcome dialog for new installs -->
|
||||
<InstallUISequence>
|
||||
<Show Dialog="ZellijWelcomeDlg" Before="ProgressDlg"
|
||||
Condition="NOT Installed" />
|
||||
</InstallUISequence>
|
||||
|
||||
<!-- WixUI_Common provides shared error/progress/cancel dialogs -->
|
||||
<UIRef Id="WixUI_Common" />
|
||||
|
||||
<!-- These variables were originally defined in the WixUI_Advanced fragment
|
||||
which we no longer use. InstallScopeDlg references them to decide
|
||||
which radio buttons to show. -->
|
||||
<WixVariable Id="WixUISupportPerUser" Value="1" />
|
||||
<WixVariable Id="WixUISupportPerMachine" Value="1" />
|
||||
|
||||
<WixVariable Id="WixUILicenseRtf" Value="wix\License.rtf" />
|
||||
<WixVariable Id="WixUIBannerBmp" Value="wix\banner.bmp" />
|
||||
<WixVariable Id="WixUIDialogBmp" Value="wix\dialog.bmp" />
|
||||
|
||||
</Package>
|
||||
</Wix>
|
||||
Reference in New Issue
Block a user