mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-02 18:11:59 +00:00
Merge pull request #760 from storytold/feat/windows-setup-wizard
Packaging: Windows MSI setup wizard (folder choice, progress, version, launch on finish)
This commit is contained in:
@@ -46,7 +46,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
- name: XML, desktop entry, AppStream, Flatpak manifest
|
- name: XML, desktop entry, AppStream, Flatpak manifest
|
||||||
run: |
|
run: |
|
||||||
xmllint --noout packaging/windows/vectorcraft.wxs packaging/macos/*.plist* packaging/linux/*.xml*
|
xmllint --noout packaging/windows/vectorcraft.wxs packaging/windows/vectorcraft.en-us.wxl packaging/macos/*.plist* packaging/linux/*.xml*
|
||||||
# Windows Installer needs Icon ids ending in .ico or .exe, or shortcuts show a blank icon.
|
# Windows Installer needs Icon ids ending in .ico or .exe, or shortcuts show a blank icon.
|
||||||
if grep -oE '<Icon Id="[^"]*"' packaging/windows/vectorcraft.wxs | grep -vE '\.(ico|exe)"$'; then
|
if grep -oE '<Icon Id="[^"]*"' packaging/windows/vectorcraft.wxs | grep -vE '\.(ico|exe)"$'; then
|
||||||
echo "::error::Icon Id must end in .ico or .exe"; exit 1
|
echo "::error::Icon Id must end in .ico or .exe"; exit 1
|
||||||
|
|||||||
@@ -150,7 +150,9 @@ jobs:
|
|||||||
run: cargo xtask version set "$VECTORCRAFT_VERSION"
|
run: cargo xtask version set "$VECTORCRAFT_VERSION"
|
||||||
- name: Install WiX
|
- name: Install WiX
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: dotnet tool install --global wix --version 5.0.2
|
run: |
|
||||||
|
dotnet tool install --global wix --version 5.0.2
|
||||||
|
wix extension add -g WixToolset.UI.wixext/5.0.2 WixToolset.Util.wixext/5.0.2
|
||||||
- name: Build, sign, package
|
- name: Build, sign, package
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ jobs:
|
|||||||
key: windows-arm64-package
|
key: windows-arm64-package
|
||||||
- name: Install WiX
|
- name: Install WiX
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: dotnet tool install --global wix --version 5.0.2
|
run: |
|
||||||
|
dotnet tool install --global wix --version 5.0.2
|
||||||
|
wix extension add -g WixToolset.UI.wixext/5.0.2 WixToolset.Util.wixext/5.0.2
|
||||||
- name: Build and package (unsigned)
|
- name: Build and package (unsigned)
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -112,6 +112,13 @@ to the target triple, so host build scripts aren't affected.
|
|||||||
- `vectorcraft.wxs` (WiX) is a per-machine install into Program Files with a Start Menu shortcut
|
- `vectorcraft.wxs` (WiX) is a per-machine install into Program Files with a Start Menu shortcut
|
||||||
and an App Paths entry (Win+R `vectorcraft`). Same-version upgrades are allowed, so release
|
and an App Paths entry (Win+R `vectorcraft`). Same-version upgrades are allowed, so release
|
||||||
candidates replace each other.
|
candidates replace each other.
|
||||||
|
- Double-clicking the MSI opens a setup wizard (WixUI_InstallDir without the licence page):
|
||||||
|
Welcome, install folder (remembered for upgrades in `HKLM\Software\VectorCraft\InstallDir`),
|
||||||
|
Ready, a progress page, and a Finish page that says where to find the app, with a ticked "Launch
|
||||||
|
VectorCraft" box. The pages name the full version (`vectorcraft.en-us.wxl`). `package.ps1` draws
|
||||||
|
the wizard's banner and side bitmaps from the app icon, so no WiX stock art ships. `msiexec /qn`
|
||||||
|
still installs silently. Building needs the WiX UI and Util extensions:
|
||||||
|
`wix extension add -g WixToolset.UI.wixext/5.0.2 WixToolset.Util.wixext/5.0.2`.
|
||||||
- The ARM64 build is cross-compiled on the x64 runner. `.github/workflows/windows-arm64.yml`
|
- The ARM64 build is cross-compiled on the x64 runner. `.github/workflows/windows-arm64.yml`
|
||||||
installs that MSI on a Windows 11 ARM64 runner, checks that both installed programs are ARM64,
|
installs that MSI on a Windows 11 ARM64 runner, checks that both installed programs are ARM64,
|
||||||
runs `vectorcraft-cli --version` natively and uninstalls.
|
runs `vectorcraft-cli --version` natively and uninstalls.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
Needs: Rust (MSVC toolchain + the target), the Windows SDK (rc.exe, signtool.exe),
|
Needs: Rust (MSVC toolchain + the target), the Windows SDK (rc.exe, signtool.exe),
|
||||||
and WiX v5: dotnet tool install --global wix --version 5.0.2
|
and WiX v5: dotnet tool install --global wix --version 5.0.2
|
||||||
|
wix extension add -g WixToolset.UI.wixext/5.0.2 WixToolset.Util.wixext/5.0.2
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
pwsh packaging/windows/package.ps1 -Arch x64
|
pwsh packaging/windows/package.ps1 -Arch x64
|
||||||
@@ -91,10 +92,50 @@ Copy-Item (Join-Path $Bin 'vectorcraft.exe'), (Join-Path $Bin 'vectorcraft-cli.e
|
|||||||
& (Join-Path $PSScriptRoot 'sign.ps1') (Join-Path $Stage 'vectorcraft.exe') (Join-Path $Stage 'vectorcraft-cli.exe')
|
& (Join-Path $PSScriptRoot 'sign.ps1') (Join-Path $Stage 'vectorcraft.exe') (Join-Path $Stage 'vectorcraft-cli.exe')
|
||||||
|
|
||||||
# ---- MSI ---------------------------------------------------------------------------------------
|
# ---- MSI ---------------------------------------------------------------------------------------
|
||||||
|
# The setup wizard's art, drawn here from the app icon so the MSI shows VectorCraft rather than
|
||||||
|
# WiX's stock bitmaps: a 493x58 banner across the top of the inner pages (the page title is drawn
|
||||||
|
# over its left side, so that stays white) and a 493x312 backdrop for the Welcome and Finish pages
|
||||||
|
# (their text sits on the right; the left 164 px are ours). Both must be 24-bit BMPs.
|
||||||
|
function New-InstallerArt([string] $IconPng, [string] $BannerOut, [string] $DialogOut) {
|
||||||
|
Add-Type -AssemblyName System.Drawing
|
||||||
|
$paper = [System.Drawing.ColorTranslator]::FromHtml('#efe9dc')
|
||||||
|
$accent = [System.Drawing.ColorTranslator]::FromHtml('#e8573f')
|
||||||
|
$icon = [System.Drawing.Image]::FromFile($IconPng)
|
||||||
|
try {
|
||||||
|
foreach ($spec in @(@($BannerOut, 493, 58), @($DialogOut, 493, 312))) {
|
||||||
|
$bmp = New-Object System.Drawing.Bitmap $spec[1], $spec[2], ([System.Drawing.Imaging.PixelFormat]::Format24bppRgb)
|
||||||
|
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
||||||
|
try {
|
||||||
|
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
|
||||||
|
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
|
||||||
|
$g.Clear([System.Drawing.Color]::White)
|
||||||
|
if ($spec[2] -eq 58) {
|
||||||
|
$g.DrawImage($icon, 493 - 46 - 8, 6, 46, 46)
|
||||||
|
} else {
|
||||||
|
$panel = New-Object System.Drawing.SolidBrush $paper
|
||||||
|
$stripe = New-Object System.Drawing.SolidBrush $accent
|
||||||
|
$g.FillRectangle($panel, 0, 0, 164, 312)
|
||||||
|
$g.FillRectangle($stripe, 160, 0, 4, 312)
|
||||||
|
$g.DrawImage($icon, 18, 64, 124, 124)
|
||||||
|
$panel.Dispose(); $stripe.Dispose()
|
||||||
|
}
|
||||||
|
} finally { $g.Dispose() }
|
||||||
|
$bmp.Save($spec[0], [System.Drawing.Imaging.ImageFormat]::Bmp)
|
||||||
|
$bmp.Dispose()
|
||||||
|
}
|
||||||
|
} finally { $icon.Dispose() }
|
||||||
|
}
|
||||||
|
$Banner = Join-Path $Stage 'installer-banner.bmp'
|
||||||
|
$Dialog = Join-Path $Stage 'installer-dialog.bmp'
|
||||||
|
New-InstallerArt (Join-Path $Root 'assets\app-icon\hicolor\256x256\apps\ai.storyteller.vectorcraft.png') $Banner $Dialog
|
||||||
|
|
||||||
$Msi = Join-Path $Dist "vectorcraft-$Version-windows-$Arch.msi"
|
$Msi = Join-Path $Dist "vectorcraft-$Version-windows-$Arch.msi"
|
||||||
Invoke-Native 'wix build' {
|
Invoke-Native 'wix build' {
|
||||||
wix build (Join-Path $PSScriptRoot 'vectorcraft.wxs') -arch $Arch `
|
wix build (Join-Path $PSScriptRoot 'vectorcraft.wxs') -arch $Arch `
|
||||||
-d "Version=$MsiVersion" -d "BinDir=$Stage" -d "IconPath=$(Join-Path $Root 'assets\app-icon\vectorcraft.ico')" `
|
-ext WixToolset.UI.wixext -ext WixToolset.Util.wixext `
|
||||||
|
-culture en-US -loc (Join-Path $PSScriptRoot 'vectorcraft.en-us.wxl') `
|
||||||
|
-d "Version=$MsiVersion" -d "DisplayVersion=$Version" -d "BinDir=$Stage" -d "IconPath=$(Join-Path $Root 'assets\app-icon\vectorcraft.ico')" `
|
||||||
|
-d "BannerBmp=$Banner" -d "DialogBmp=$Dialog" `
|
||||||
-o $Msi
|
-o $Msi
|
||||||
}
|
}
|
||||||
# wix writes its debug symbols (.wixpdb) next to the MSI; keep them out of the release assets.
|
# wix writes its debug symbols (.wixpdb) next to the MSI; keep them out of the release assets.
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Overrides for the setup wizard's WixUI strings, so its pages name the version being installed
|
||||||
|
([VectorcraftVersion] is the full version, pre-release tag included, set in vectorcraft.wxs).
|
||||||
|
-->
|
||||||
|
<WixLocalization Culture="en-US" xmlns="http://wixtoolset.org/schemas/v4/wxl">
|
||||||
|
<String Id="WelcomeDlgTitle" Value="{\WixUI_Font_Bigger}Welcome to the [ProductName] [VectorcraftVersion] Setup Wizard" />
|
||||||
|
<String Id="WelcomeDlgDescription" Value="The Setup Wizard will install [ProductName] version [VectorcraftVersion] on your computer. Click Next to continue or Cancel to exit the Setup Wizard." />
|
||||||
|
<String Id="VerifyReadyDlgInstallTitle" Value="{\WixUI_Font_Title}Ready to install [ProductName] [VectorcraftVersion]" />
|
||||||
|
<String Id="ExitDialogTitle" Value="{\WixUI_Font_Bigger}Completed the [ProductName] [VectorcraftVersion] Setup Wizard" />
|
||||||
|
</WixLocalization>
|
||||||
@@ -1,13 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
VectorCraft MSI (WiX Toolset v5: `dotnet tool install -g wix`). Built by package.ps1:
|
VectorCraft MSI (WiX Toolset v5: `dotnet tool install -g wix`, plus the UI and Util extensions:
|
||||||
|
`wix extension add -g WixToolset.UI.wixext/5.0.2 WixToolset.Util.wixext/5.0.2`). Built by package.ps1:
|
||||||
|
|
||||||
wix build vectorcraft.wxs -arch x64 -d Version=1.2.3 -d BinDir=... -d IconPath=... -o out.msi
|
wix build vectorcraft.wxs -arch x64 -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext
|
||||||
|
-culture en-US -loc vectorcraft.en-us.wxl -d Version=1.2.3 -d DisplayVersion=1.2.3-rc.1
|
||||||
|
-d BinDir=... -d IconPath=... -d BannerBmp=... -d DialogBmp=... -o out.msi
|
||||||
|
|
||||||
Per-machine install into Program Files, a Start Menu shortcut and an App Paths entry (so
|
Per-machine install with a setup wizard that names the version: Welcome, install folder (Program Files\VectorCraft by
|
||||||
`vectorcraft` starts from the Run dialog), plus vectorcraft-cli.
|
default, remembered for upgrades), Ready, a progress page, and a Finish page with a ticked
|
||||||
|
"Launch VectorCraft" box. Installs a Start Menu shortcut and an App Paths entry (so `vectorcraft`
|
||||||
|
starts from the Run dialog), plus vectorcraft-cli. `msiexec /qn` still installs silently.
|
||||||
-->
|
-->
|
||||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
||||||
|
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
|
||||||
<Package
|
<Package
|
||||||
Name="VectorCraft"
|
Name="VectorCraft"
|
||||||
Manufacturer="Learning Machines LLC"
|
Manufacturer="Learning Machines LLC"
|
||||||
@@ -34,9 +40,39 @@
|
|||||||
</StandardDirectory>
|
</StandardDirectory>
|
||||||
<StandardDirectory Id="ProgramMenuFolder" />
|
<StandardDirectory Id="ProgramMenuFolder" />
|
||||||
|
|
||||||
|
<!-- An upgrade installs where the user put the previous version (written by VectorcraftApp). -->
|
||||||
|
<Property Id="INSTALLFOLDER">
|
||||||
|
<RegistrySearch Id="PreviousInstallFolder" Root="HKLM" Key="Software\VectorCraft" Name="InstallDir" Type="raw" />
|
||||||
|
</Property>
|
||||||
|
|
||||||
<Feature Id="Main" Title="VectorCraft" Level="1">
|
<Feature Id="Main" Title="VectorCraft" Level="1">
|
||||||
<ComponentGroupRef Id="VectorcraftFiles" />
|
<ComponentGroupRef Id="VectorcraftFiles" />
|
||||||
</Feature>
|
</Feature>
|
||||||
|
|
||||||
|
<!-- The setup wizard: WixUI_InstallDir without its licence page (the code is MIT OR
|
||||||
|
Apache-2.0; there is nothing to accept). A later NewDialog on the same button wins. -->
|
||||||
|
<ui:WixUI Id="WixUI_InstallDir" InstallDirectory="INSTALLFOLDER" />
|
||||||
|
<UI>
|
||||||
|
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2" Condition="NOT Installed" />
|
||||||
|
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2" />
|
||||||
|
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchVectorcraft"
|
||||||
|
Condition="WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 AND NOT Installed" />
|
||||||
|
</UI>
|
||||||
|
<!-- Our own art, generated by package.ps1 from the app icon (not WiX's stock bitmaps). -->
|
||||||
|
<WixVariable Id="WixUIBannerBmp" Value="$(var.BannerBmp)" />
|
||||||
|
<WixVariable Id="WixUIDialogBmp" Value="$(var.DialogBmp)" />
|
||||||
|
|
||||||
|
<!-- The full version (Version is numeric, so it drops a pre-release tag), shown on the wizard's
|
||||||
|
pages through vectorcraft.en-us.wxl. -->
|
||||||
|
<Property Id="VectorcraftVersion" Value="$(var.DisplayVersion)" />
|
||||||
|
|
||||||
|
<!-- Finish page: say where to find the app, and offer to start it (ticked by default). -->
|
||||||
|
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT" Value="VectorCraft $(var.DisplayVersion) is installed. You can start it any time from the Start menu." />
|
||||||
|
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch VectorCraft" />
|
||||||
|
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
|
||||||
|
<Property Id="WixShellExecTarget" Value="[#VectorcraftExe]" />
|
||||||
|
<!-- Runs in the wizard's own (unelevated) process, so the app starts as the user, not as admin. -->
|
||||||
|
<CustomAction Id="LaunchVectorcraft" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixShellExec" Impersonate="yes" Return="ignore" />
|
||||||
</Package>
|
</Package>
|
||||||
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@@ -49,6 +85,7 @@
|
|||||||
</File>
|
</File>
|
||||||
|
|
||||||
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\vectorcraft.exe" Value="[#VectorcraftExe]" Type="string" />
|
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\vectorcraft.exe" Value="[#VectorcraftExe]" Type="string" />
|
||||||
|
<RegistryValue Root="HKLM" Key="Software\VectorCraft" Name="InstallDir" Value="[INSTALLFOLDER]" Type="string" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<Component Id="VectorcraftCli">
|
<Component Id="VectorcraftCli">
|
||||||
|
|||||||
Reference in New Issue
Block a user