diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a438814..bdf41d6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on: version: description: 'Build & package version' required: true - default: 0.1.4 + default: 0.1.5 type: string jobs: Build: diff --git a/MsiZapEx/ComponentInfo.cs b/MsiZapEx/ComponentInfo.cs index eae2c34..abcc039 100644 --- a/MsiZapEx/ComponentInfo.cs +++ b/MsiZapEx/ComponentInfo.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; +using System.Threading; namespace MsiZapEx { @@ -40,43 +41,31 @@ internal ProductKeyPath(Guid productCode, string keyPath, bool exists) public List ProductsKeyPath { get; } = new List(); private static List _components = new List(); + private static ManualResetEventSlim _componentsLock = new ManualResetEventSlim(false); internal static List GetAllComponents() { - if (_components.Count > 0) + if (_componentsLock.IsSet) { return _components; } - using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) + try { - using (RegistryKey k = hklm.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{ProductInfo.LocalSystemSID}\Components", false)) + _componentsLock.Set(); + if (_components.Count > 0) { - if (k == null) - { - throw new FileNotFoundException(); - } + return _components; + } - string[] componentCodes = k.GetSubKeyNames(); - foreach (string c in componentCodes) + using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) + { + using (RegistryKey k = hklm.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{ProductInfo.LocalSystemSID}\Components", false)) { - // Ignore default value - if (string.IsNullOrWhiteSpace(c) || c.Equals("@") || !Guid.TryParse(c, out Guid id) || id.Equals(Guid.Empty)) + if (k == null) { - continue; + throw new FileNotFoundException(); } - Guid componentCode = GuidEx.MsiObfuscate(c); - ComponentInfo ci = _components.FirstOrDefault(cc => cc.MachineScope && cc.ComponentCode.Equals(componentCode)); - if (ci == null) - { - ci = new ComponentInfo(c, true); - } - } - } - using (RegistryKey k = hklm.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{ProductInfo.CurrentUserSID}\Components", false)) - { - if (k != null) - { string[] componentCodes = k.GetSubKeyNames(); foreach (string c in componentCodes) { @@ -87,15 +76,41 @@ internal static List GetAllComponents() } Guid componentCode = GuidEx.MsiObfuscate(c); - ComponentInfo ci = _components.FirstOrDefault(cc => !cc.MachineScope && cc.ComponentCode.Equals(componentCode)); + ComponentInfo ci = _components.FirstOrDefault(cc => cc.MachineScope && cc.ComponentCode.Equals(componentCode)); if (ci == null) { - ci = new ComponentInfo(c, false); + ci = new ComponentInfo(c, true); + } + } + } + using (RegistryKey k = hklm.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{ProductInfo.CurrentUserSID}\Components", false)) + { + if (k != null) + { + string[] componentCodes = k.GetSubKeyNames(); + foreach (string c in componentCodes) + { + // Ignore default value + if (string.IsNullOrWhiteSpace(c) || c.Equals("@") || !Guid.TryParse(c, out Guid id) || id.Equals(Guid.Empty)) + { + continue; + } + + Guid componentCode = GuidEx.MsiObfuscate(c); + ComponentInfo ci = _components.FirstOrDefault(cc => !cc.MachineScope && cc.ComponentCode.Equals(componentCode)); + if (ci == null) + { + ci = new ComponentInfo(c, false); + } } } } } } + finally + { + _componentsLock.Reset(); + } return _components; } @@ -131,13 +146,18 @@ public ComponentInfo(Guid componentCode, bool? machineScope = null) internal ComponentInfo(string obfuscatedGuid, bool? machineScope = null) { - Guid componentCode = GuidEx.MsiObfuscate(obfuscatedGuid); - this.MachineScope = machineScope ?? ResolveScope(componentCode); - ComponentInfo ci = _components.FirstOrDefault(c => c.MachineScope == machineScope && c.ComponentCode.Equals(componentCode)); + GetAllComponents(); + + ComponentCode = GuidEx.MsiObfuscate(obfuscatedGuid); + if (machineScope == null) + { + machineScope = ResolveScope(ComponentCode); + } + this.MachineScope = machineScope.Value; + ComponentInfo ci = _components.FirstOrDefault(c => c.MachineScope == machineScope && c.ComponentCode.Equals(ComponentCode)); if (ci != null) { this.Status = ci.Status; - this.ComponentCode = ci.ComponentCode; this.ProductsKeyPath.AddRange(ci.ProductsKeyPath); return; } @@ -183,6 +203,7 @@ internal void PrintProducts() if (ProductsKeyPath.Count == 0) { Console.WriteLine($"Component '{ComponentCode}' is not related to any product"); + return; } Console.WriteLine($"Component '{ComponentCode}' belongs to {ProductsKeyPath.Count} products"); diff --git a/MsiZapEx/ProductInfo.cs b/MsiZapEx/ProductInfo.cs index 466bd47..5252b5a 100644 --- a/MsiZapEx/ProductInfo.cs +++ b/MsiZapEx/ProductInfo.cs @@ -143,6 +143,7 @@ public void PrintState() if (Settings.Instance.Verbose) { Console.WriteLine($"\tFeatures: {Features.Aggregate((a, c) => $"{a}, {c}")}"); + Console.WriteLine($"\tLocalPackage: {LocalPackage}"); } }