Skip to content

Commit

Permalink
Support WiX v4 bundles (registry x86 / x64)
Browse files Browse the repository at this point in the history
  • Loading branch information
nirbar committed Jul 2, 2023
1 parent 1ed4558 commit 9986272
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
version:
description: 'Build & package version'
required: true
default: 0.0.14
default: 0.1.0
type: string
jobs:
Build:
Expand Down
42 changes: 27 additions & 15 deletions MsiZapEx/BundleInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.Win32;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -9,7 +9,7 @@ namespace MsiZapEx

public class BundleInfo
{
// HKLM32 Software\Microsoft\Windows\CurrentVersion\Uninstall\<BundleProductCode>
// HKLM32/HKLM64 Software\Microsoft\Windows\CurrentVersion\Uninstall\<BundleProductCode>
// HKCR HKEY_CLASSES_ROOT\Installer\Dependencies\<MsiProductCode or BundleBundleProviderKey>\@ = <MsiProductCode Or BundleProductCode>
// HKCR HKEY_CLASSES_ROOT\Installer\Dependencies\*\Dependents\<BundleProductCode>
[Flags]
Expand All @@ -25,6 +25,7 @@ public enum StatusFlags
Good = ProviderKeyProductCodeMatch | HkcrDependencies | ArpPorviderKey | ArpUpgradeCodes | ARP
}

public RegistryView RegistryView { get; private set; }
public Guid BundleProductCode { get; private set; } = Guid.Empty;
public List<Guid> BundleUpgradeCodes { get; private set; } = new List<Guid>();
public string BundleProviderKey { get; private set; }
Expand All @@ -36,12 +37,20 @@ public enum StatusFlags
public StatusFlags Status { get; private set; } = StatusFlags.None;

public static List<BundleInfo> FindByUpgradeCode(Guid bundleUpgradeCode)
{
List<BundleInfo> bundles = new List<BundleInfo>();
bundles.AddRange(FindByUpgradeCode(bundleUpgradeCode, RegistryView.Registry32));
bundles.AddRange(FindByUpgradeCode(bundleUpgradeCode, RegistryView.Registry64));
return bundles;
}

private static List<BundleInfo> FindByUpgradeCode(Guid bundleUpgradeCode, RegistryView view)
{
List<BundleInfo> bundles = new List<BundleInfo>();

using (RegistryKey hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view))
{
using (RegistryKey hkUninstall = hklm32.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false))
using (RegistryKey hkUninstall = hklm.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false))
{
if (hkUninstall == null)
{
Expand Down Expand Up @@ -75,15 +84,15 @@ public static List<BundleInfo> FindByUpgradeCode(Guid bundleUpgradeCode)
case RegistryValueKind.String:
if (Guid.TryParse(hkSubkey.GetValue("BundleUpgradeCode")?.ToString(), out Guid bug) && bug.Equals(bundleUpgradeCode))
{
BundleInfo bundle = new BundleInfo(bundleProductCode);
BundleInfo bundle = new BundleInfo(bundleProductCode, view);
bundles.Add(bundle);
}
continue;

case RegistryValueKind.MultiString:
if ((hkSubkey.GetValue("BundleUpgradeCode") is IEnumerable<string> bugs) && bugs.Any(uc => Guid.TryParse(uc, out Guid bug1) && bug1.Equals(bundleUpgradeCode)))
{
BundleInfo bundle = new BundleInfo(bundleProductCode);
BundleInfo bundle = new BundleInfo(bundleProductCode, view);
bundles.Add(bundle);
}
break;
Expand All @@ -101,7 +110,7 @@ public void Prune()
{
if (!BundleProductCode.Equals(Guid.Empty))
{
modifier.DeferDeleteKey(RegistryHive.LocalMachine, RegistryView.Registry32, $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{BundleProductCode.ToString("B")}");
modifier.DeferDeleteKey(RegistryHive.LocalMachine, RegistryView, $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{BundleProductCode.ToString("B")}");

foreach (string d in Dependents)
{
Expand Down Expand Up @@ -146,6 +155,7 @@ internal void PrintState()
if (!BundleProductCode.Equals(Guid.Empty))
{
Console.WriteLine($"\tBundleProductCode '{BundleProductCode}'");
Console.WriteLine($"\tBitness '{RegistryView}'");
}

if (!Status.HasFlag(StatusFlags.ArpUpgradeCodes))
Expand Down Expand Up @@ -194,9 +204,9 @@ internal void PrintState()
}
}

public BundleInfo(Guid bundleProductCode)
public BundleInfo(Guid bundleProductCode, RegistryView? view = null)
{
ReadARP(bundleProductCode);
ReadARP(bundleProductCode, view);
}

private void ReadDependencies(string bundleProviderKey)
Expand All @@ -219,10 +229,6 @@ private void ReadDependencies(string bundleProviderKey)

if (Guid.TryParse(hkProviderKey.GetValue("")?.ToString(), out Guid bpc))
{
if (BundleProductCode.Equals(Guid.Empty))
{
ReadARP(bpc);
}
if (BundleProductCode.Equals(bpc))
{
Status |= StatusFlags.ProviderKeyProductCodeMatch;
Expand Down Expand Up @@ -262,18 +268,24 @@ private void ReadDependencies(string bundleProviderKey)
}
}

private void ReadARP(Guid bundleProductCode)
private void ReadARP(Guid bundleProductCode, RegistryView? view)
{
BundleProductCode = bundleProductCode;
using (RegistryKey hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
RegistryView implicitView = view ?? RegistryView.Registry32;
using (RegistryKey hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, implicitView))
{
using (RegistryKey hkUninstall = hklm32.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{bundleProductCode.ToString("B")}", false))
{
if (hkUninstall == null)
{
if (view == null)
{
ReadARP(bundleProductCode, RegistryView.Registry64);
}
return;
}
Status |= StatusFlags.ARP;
RegistryView = implicitView;

RegistryValueKind valueKind = hkUninstall.GetValueKind("BundleUpgradeCode");
switch (valueKind)
Expand Down

0 comments on commit 9986272

Please sign in to comment.