mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-26 11:09:23 -06:00
The App Paths directory search doesn't check that lightcraft.exe exists, and when the old installers' unquoted path is gone, Windows Installer falls back to the text before the first space: a deleted C:\Program Files\LightCraft\lightcraft.exe resolved to C:\, so an upgrade would install into the drive root. Gate the fallback on a second search of the same value with a FileSearch for lightcraft.exe. The install-folder test gains legacy-folder-deleted (failed before this fix) and legacy-exe-deleted cases, and removes its empty parent registry key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
205 lines
12 KiB
XML
205 lines
12 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!--
|
|
LightCraft 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 lightcraft.wxs -arch x64 -ext WixToolset.UI.wixext/5.0.2 -ext WixToolset.Util.wixext/5.0.2
|
|
-d Version=1.2.3 -d BinDir=... -d IconPath=... -d UiDialogBmp=... -d UiBannerBmp=... -o out.msi
|
|
|
|
Per-machine install into Program Files (or the folder chosen in the installer, or
|
|
`INSTALLFOLDER=...` on the msiexec command line; upgrades keep it), a Start Menu shortcut, `.pcraft` owned by LightCraft,
|
|
and LightCraft offered under "Open with" for PSD/PSB and the image formats it reads (without
|
|
taking over the user's default app for them).
|
|
-->
|
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
|
<Package
|
|
Name="LightCraft"
|
|
Manufacturer="Learning Machines LLC"
|
|
Version="$(var.Version)"
|
|
UpgradeCode="229BB552-5EFD-479A-BA86-8CB6D926390C"
|
|
Scope="perMachine"
|
|
Compressed="yes"
|
|
Language="1033">
|
|
<SummaryInformation Description="LightCraft photo library and raw developer" Manufacturer="Learning Machines LLC" />
|
|
<!-- Same-version upgrades let successive pre-releases of one X.Y.Z replace each other
|
|
(MSI versions are numeric, so 1.2.3-rc.1 and 1.2.3-rc.2 are both 1.2.3). -->
|
|
<MajorUpgrade AllowSameVersionUpgrades="yes"
|
|
DowngradeErrorMessage="A newer version of LightCraft is already installed." />
|
|
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
|
|
|
|
<Icon Id="LightcraftIcon.ico" SourceFile="$(var.IconPath)" />
|
|
<Property Id="ARPPRODUCTICON" Value="LightcraftIcon.ico" />
|
|
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/lightcraft" />
|
|
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/lightcraft" />
|
|
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
|
|
|
|
<StandardDirectory Id="ProgramFiles6432Folder">
|
|
<Directory Id="INSTALLFOLDER" Name="LightCraft" />
|
|
</StandardDirectory>
|
|
<!-- The folder of the installed version (written by LightcraftApp), so an upgrade installs
|
|
where the user chose instead of moving back to Program Files (issue #399). Searched into
|
|
its own property: AppSearch would otherwise overwrite INSTALLFOLDER=... given to msiexec. -->
|
|
<Property Id="PREVIOUSINSTALLFOLDER">
|
|
<RegistrySearch Id="PreviousInstallFolder" Root="HKLM" Key="Software\LightCraft" Name="InstallFolder" Type="raw" />
|
|
</Property>
|
|
<SetProperty Id="INSTALLFOLDER" Value="[PREVIOUSINSTALLFOLDER]" After="AppSearch" Sequence="both"
|
|
Condition="PREVIOUSINSTALLFOLDER AND NOT INSTALLFOLDER" />
|
|
<!-- Older MSIs (including 0.5.0) only recorded the executable in App Paths. Type="file"
|
|
without a FileSearch returns its containing directory. Keep the searches separate so
|
|
the newer InstallFolder value and an explicit INSTALLFOLDER always take precedence. -->
|
|
<Property Id="LEGACYINSTALLFOLDER">
|
|
<RegistrySearch Id="LegacyInstallFolder" Root="HKLM"
|
|
Key="Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe" Type="file" />
|
|
</Property>
|
|
<!-- That directory search doesn't check the executable exists, and when its unquoted path is
|
|
gone it falls back to the text before the first space: a deleted
|
|
"C:\Program Files\LightCraft\lightcraft.exe" yields "C:\". Only use the folder when this
|
|
search, which does require lightcraft.exe, finds it too. -->
|
|
<Property Id="LEGACYINSTALLEXE">
|
|
<RegistrySearch Id="LegacyInstallExe" Root="HKLM"
|
|
Key="Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe" Type="file">
|
|
<FileSearch Id="LegacyInstallExeFile" Name="lightcraft.exe" />
|
|
</RegistrySearch>
|
|
</Property>
|
|
<SetProperty Id="INSTALLFOLDER" Action="SetInstallFolderFromAppPaths" Value="[LEGACYINSTALLFOLDER]"
|
|
After="SetINSTALLFOLDER" Sequence="both"
|
|
Condition="LEGACYINSTALLFOLDER AND LEGACYINSTALLEXE AND NOT PREVIOUSINSTALLFOLDER AND NOT INSTALLFOLDER" />
|
|
<StandardDirectory Id="ProgramMenuFolder" />
|
|
|
|
<Feature Id="Main" Title="LightCraft" Level="1">
|
|
<ComponentGroupRef Id="LightcraftFiles" />
|
|
</Feature>
|
|
|
|
<UIRef Id="LightcraftUI" />
|
|
</Package>
|
|
|
|
<!--
|
|
Interactive install UI: Welcome -> Destination Folder -> Ready to install -> progress ->
|
|
"Completed" (Finish), with a "Launch LightCraft" checkbox (checked by default). Destination
|
|
Folder (issue #399) shows Program Files\LightCraft, or the installed version's folder on an
|
|
upgrade; Change... browses, and a folder that can't be used (InvalidDirDlg) is refused before
|
|
anything is installed. Failure and cancellation end on WiX's standard FatalError / UserExit
|
|
dialogs instead of the completion page. Maintenance (running the MSI again, Repair/Remove from
|
|
Apps) uses the standard maintenance dialogs.
|
|
|
|
This is WixUI_InstallDir without its licence-acceptance page: LightCraft is MIT OR Apache-2.0,
|
|
which ask nothing of people who just install and run it, so a click-through EULA would only
|
|
add a step. Silent (/qn) and basic-UI (/passive, /qb) installs never show these dialogs, so
|
|
they are unaffected, and nothing is launched.
|
|
|
|
The dialogs, strings and error/cancel pages come from WixToolset.UI.wixext; the side and
|
|
banner bitmaps are plain panels generated by package.ps1 (no third-party artwork).
|
|
-->
|
|
<Fragment>
|
|
<WixVariable Id="WixUIDialogBmp" Value="$(var.UiDialogBmp)" />
|
|
<WixVariable Id="WixUIBannerBmp" Value="$(var.UiBannerBmp)" />
|
|
|
|
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT"
|
|
Value="LightCraft has been installed. You can start it at any time from the Start menu." />
|
|
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch LightCraft" />
|
|
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
|
|
|
|
<!-- "Launch LightCraft" on Finish. WixUnelevatedShellExec (Util extension) asks the desktop
|
|
shell (Explorer) to start the program, so it runs as the signed-in user at normal
|
|
integrity even when the installer UI itself is elevated (e.g. msiexec started from an
|
|
admin prompt); it never runs from the elevated/SYSTEM server side. It is a UI-only control
|
|
event, so silent and passive installs never run it. Return="ignore": a failed launch must
|
|
not turn a successful install into an error. -->
|
|
<Property Id="WixUnelevatedShellExecTarget" Value="[#LightcraftExe]" />
|
|
<CustomAction Id="LaunchLightcraft" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)"
|
|
DllEntry="WixUnelevatedShellExec" Execute="immediate" Impersonate="yes" Return="ignore" />
|
|
|
|
<UI Id="LightcraftUI">
|
|
<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="ErrorDlg" />
|
|
<DialogRef Id="FatalError" />
|
|
<DialogRef Id="FilesInUse" />
|
|
<DialogRef Id="MsiRMFilesInUse" />
|
|
<DialogRef Id="PrepareDlg" />
|
|
<DialogRef Id="ProgressDlg" />
|
|
<DialogRef Id="ResumeDlg" />
|
|
<DialogRef Id="UserExit" />
|
|
<DialogRef Id="WelcomeDlg" />
|
|
<DialogRef Id="InstallDirDlg" />
|
|
<DialogRef Id="BrowseDlg" />
|
|
<DialogRef Id="InvalidDirDlg" />
|
|
<DialogRef Id="DiskCostDlg" />
|
|
<DialogRef Id="VerifyReadyDlg" />
|
|
<DialogRef Id="MaintenanceWelcomeDlg" />
|
|
<DialogRef Id="MaintenanceTypeDlg" />
|
|
|
|
<!-- The folder InstallDirDlg edits. -->
|
|
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
|
|
|
|
<!-- First install / upgrade: Welcome -> Destination Folder -> Ready to install. A patch skips
|
|
the folder (it can't move an installed product). -->
|
|
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Condition="NOT Installed" />
|
|
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Condition="Installed AND PATCH" />
|
|
|
|
<!-- Destination Folder, as in WixUI_InstallDir: Next sets the folder, validates it (WiX's
|
|
WixUIValidatePath) and refuses one that can't be used; Change... opens the folder browser,
|
|
whose OK validates too. -->
|
|
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" />
|
|
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1" />
|
|
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath_$(sys.BUILDARCHSHORT)" Order="2"
|
|
Condition="NOT WIXUI_DONTVALIDATEPATH" />
|
|
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"
|
|
Condition="NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"" />
|
|
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4"
|
|
Condition="WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"" />
|
|
<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="DoAction" Value="WixUIValidatePath_$(sys.BUILDARCHSHORT)" Order="3"
|
|
Condition="NOT WIXUI_DONTVALIDATEPATH" />
|
|
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"
|
|
Condition="NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"" />
|
|
|
|
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1"
|
|
Condition="NOT Installed" />
|
|
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3"
|
|
Condition="Installed AND PATCH" />
|
|
|
|
<!-- Maintenance: Welcome -> Repair / Remove -> Ready. -->
|
|
<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" />
|
|
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2"
|
|
Condition="Installed AND NOT PATCH" />
|
|
|
|
<!-- Completion page: optionally launch, then close. -->
|
|
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchLightcraft" Order="1"
|
|
Condition="WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 AND NOT Installed" />
|
|
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999" />
|
|
|
|
<!-- One feature, nothing to change: no "Change" in Apps & features. -->
|
|
<Property Id="ARPNOMODIFY" Value="1" />
|
|
</UI>
|
|
|
|
<UIRef Id="WixUI_Common" />
|
|
</Fragment>
|
|
|
|
<Fragment>
|
|
<ComponentGroup Id="LightcraftFiles" Directory="INSTALLFOLDER">
|
|
<Component Id="LightcraftApp" Guid="8A1D3A39-F7C1-47B1-97AE-40C80BF82F4A">
|
|
<File Id="LightcraftExe" Source="$(var.BinDir)\lightcraft.exe" KeyPath="yes">
|
|
<Shortcut Id="StartMenuShortcut" Directory="ProgramMenuFolder" Name="LightCraft"
|
|
Description="LightCraft photo library and raw developer" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
|
|
Icon="LightcraftIcon.ico" IconIndex="0" />
|
|
</File>
|
|
|
|
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe" Value="[#LightcraftExe]" Type="string" />
|
|
<RegistryValue Root="HKLM" Key="Software\LightCraft" Name="InstallFolder" Value="[INSTALLFOLDER]" Type="string" />
|
|
</Component>
|
|
|
|
<Component Id="LightcraftCli">
|
|
<File Id="LightcraftCliExe" Source="$(var.BinDir)\lightcraft-cli.exe" KeyPath="yes" />
|
|
</Component>
|
|
</ComponentGroup>
|
|
</Fragment>
|
|
</Wix>
|