* fix(msi): keep only native ProductCode uninstall entry
Move installer state outside the Uninstall registry path,
clean up legacy duplicate entries, and use the MSI ProductCode
for updates and uninstalling.
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(msi): harden update and uninstall handling
- handle legacy EXE updates without an MSI ProductCode
- propagate MsiExec uninstall failures
- validate and XML-quote custom ARP values
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(msi): validate registry state before update and uninstall
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(msi): pass WindowsInstaller state to elevated sequence
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(msi): block unsupported MSI-to-EXE upgrades
- resolve native MSI state and ProductCode safely
- suppress reboot while preserving MSI uninstall results
- publish the resolved ARP install location
- skip invalid unrelated MSI uninstall entries
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(msi): fail uninstall when ProductCode is missing
Prevent known MSI installations from falling back to
EXE cleanup when the ProductCode cannot be resolved.
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(msi): do not abort update on ARP version write failure
Signed-off-by: fufesou <linlong1266@gmail.com>
---------
Signed-off-by: fufesou <linlong1266@gmail.com>
Rebranding recompressed the whole ~100MB payload because one cabinet held
everything. In template mode preprocess.py puts the handful of files a custom
client replaces on a second cabinet, so a patch rebuilds a few hundred KB and
leaves the payload cabinet alone. The shipped msi is built without template
mode and keeps its single cabinet.
The branding assets need conditional components. A stock build ships none of
them -- there is no icon.ico, icon.png or logo*.png, only icon.svg -- so the
template has to carry placeholders for the File rows to exist, and a customer
supplies whichever they want. Installing a placeholder unconditionally would
give a customer with no logo a placeholder image, where today a missing asset
means no logo at all: the client tries each candidate and treats the failure as
absence. So each optional asset installs only when its property says the
customer supplied one.
CI creates those placeholders and builds the template with the new mode.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7fBdTwziR5BHTkSz7Tzcm