Skip to content

Commit

Permalink
Support WiX3-compantible auto-guids for registry key path
Browse files Browse the repository at this point in the history
  • Loading branch information
nirbar committed Jan 15, 2025
1 parent 523c66a commit 08d0115
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/api/wix/WixToolset.Data/Symbols/ComponentSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public static partial class SymbolDefinitions
new IntermediateFieldDefinition(nameof(ComponentSymbolFields.Condition), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(ComponentSymbolFields.KeyPath), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(ComponentSymbolFields.KeyPathType), IntermediateFieldType.Number),
new IntermediateFieldDefinition(nameof(ComponentSymbolFields.WiX3CompatibleGuid), IntermediateFieldType.Bool),
},
typeof(ComponentSymbol));
}
Expand All @@ -47,6 +48,7 @@ public enum ComponentSymbolFields
Condition,
KeyPath,
KeyPathType,
WiX3CompatibleGuid,
}

public enum ComponentLocation
Expand Down Expand Up @@ -151,5 +153,11 @@ public ComponentKeyPathType KeyPathType
get => (ComponentKeyPathType)this.Fields[(int)ComponentSymbolFields.KeyPathType].AsNumber();
set => this.Set((int)ComponentSymbolFields.KeyPathType, (int)value);
}

public bool WiX3CompatibleGuid
{
get => this.Fields[(int)ComponentSymbolFields.WiX3CompatibleGuid].AsBool();
set => this.Set((int)ComponentSymbolFields.WiX3CompatibleGuid, value);
}
}
}
}
6 changes: 6 additions & 0 deletions src/api/wix/WixToolset.Data/WarningMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,11 @@ public static Message VBScriptIsDeprecated(SourceLineNumber sourceLineNumbers)
return Message(sourceLineNumbers, Ids.VBScriptIsDeprecated, "VBScript is a deprecated Windows component: https://learn.microsoft.com/en-us/windows/whats-new/deprecated-features. VBScript custom actions might fail on some Windows systems. Rewrite or eliminate VBScript custom actions for best compatibility.");
}

public static Message AlreadyWiX3CompatibleGuid(SourceLineNumber sourceLineNumbers, ComponentKeyPathType keyPathType)
{
return Message(sourceLineNumbers, Ids.AlreadyWiX3CompatibleGuid, "Components with KeyPath type {0} have WiX3-compatible GUID by default. Attribute WiX3CompatibleGuid is redundant.", keyPathType);
}

private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
{
return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args);
Expand Down Expand Up @@ -861,6 +866,7 @@ public enum Ids
ExePackageDetectInformationRecommended = 1161,
InvalidWixVersion = 1162,
VBScriptIsDeprecated = 1163,
AlreadyWiX3CompatibleGuid = 1164,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ private void GenerateComponentGuid(ComponentSymbol componentSymbol)
{
var bitness = componentSymbol.Win64 ? "64" : String.Empty;
var regkey = String.Concat(bitness, registrySymbol.Root, "\\", registrySymbol.Key, "\\", registrySymbol.Name);
if (componentSymbol.WiX3CompatibleGuid)
{
regkey = String.Concat(bitness, (int)registrySymbol.Root, "\\", registrySymbol.Key, "\\", registrySymbol.Name);
}
componentSymbol.ComponentId = this.BackendHelper.CreateGuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant());
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/wix/WixToolset.Core/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2125,6 +2125,7 @@ private void ParseComponentElement(XElement node, ComplexReferenceParentType par
var location = ComponentLocation.LocalOnly;
var disableRegistryReflection = false;

var wiX3CompatibleGuid = false;
var neverOverwrite = false;
var permanent = false;
var shared = false;
Expand Down Expand Up @@ -2189,6 +2190,9 @@ private void ParseComponentElement(XElement node, ComplexReferenceParentType par
case "Guid":
guid = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true, true);
break;
case "WiX3CompatibleGuid":
wiX3CompatibleGuid = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
break;
case "KeyPath":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
Expand Down Expand Up @@ -2523,6 +2527,15 @@ private void ParseComponentElement(XElement node, ComplexReferenceParentType par
}
}

if (wiX3CompatibleGuid && (guid != "*"))
{
this.Core.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, node.Name.LocalName, "WiX3CompatibleGuid", "yes", "Guid", "*"));
}
if (wiX3CompatibleGuid && (ComponentKeyPathType.Registry != keyPathType))
{
this.Core.Write(WarningMessages.AlreadyWiX3CompatibleGuid(sourceLineNumbers, keyPathType));
}

// finally add the Component table row
if (!this.Core.EncounteredError)
{
Expand All @@ -2542,6 +2555,7 @@ private void ParseComponentElement(XElement node, ComplexReferenceParentType par
Transitive = transitive,
UninstallWhenSuperseded = uninstallWhenSuperseded,
Win64 = win64,
WiX3CompatibleGuid = wiX3CompatibleGuid,
});

if (multiInstance)
Expand Down
66 changes: 66 additions & 0 deletions src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace WixToolsetTest.CoreIntegration
{
using System;
using System.IO;
using System.Linq;
using WixInternal.Core.TestPackage;
Expand Down Expand Up @@ -214,6 +215,71 @@ public void PopulatesAppSearchTablesFromRegistrySearch64()
}
}

[Fact]
public void WiX3CompatibleGuid()
{
var folder = TestData.Get(@"TestData\WiX3CompatibleGuid");

using (var fs = new DisposableFileSystem())
{
var baseFolder = fs.GetFolder();
var intermediateFolder = Path.Combine(baseFolder, "obj");
var msiPath = Path.Combine(baseFolder, @"bin\test.msi");

var result = WixRunner.Execute(new[]
{
"build",
Path.Combine(folder, "Package.wxs"),
Path.Combine(folder, "WiX3CompatibleGuid.wxs"),
"-intermediateFolder", intermediateFolder,
"-o", msiPath
});

result.AssertSuccess();

Assert.True(File.Exists(msiPath));
var results = Query.QueryDatabase(msiPath, new[] { "Component" });

Assert.Equal(2, results.Length);
Assert.Contains(results, component => component.Contains("WiX3CompatibleGuid") && component.Contains("8BAF5399-2FD2-50B6-ABDA-98FB3A5BB148", StringComparison.InvariantCultureIgnoreCase));
Assert.Contains(results, component => component.Contains("WiX4CompatibleGuid") && !component.Contains("8BAF5399-2FD2-50B6-ABDA-98FB3A5BB148", StringComparison.InvariantCultureIgnoreCase));
}
}

[Fact]
public void WiX4CompatibleGuid()
{
var folder = TestData.Get(@"TestData\WiX4CompatibleGuid");

using (var fs = new DisposableFileSystem())
{
var baseFolder = fs.GetFolder();
var intermediateFolder = Path.Combine(baseFolder, "obj");
var msiPath = Path.Combine(baseFolder, @"bin\test.msi");

var result = WixRunner.Execute(new[]
{
"build",
Path.Combine(folder, "Package.wxs"),
Path.Combine(folder, "WiX4CompatibleGuid.wxs"),
"-intermediateFolder", intermediateFolder,
"-o", msiPath
});

result.AssertSuccess();

Assert.True(File.Exists(msiPath));
var results = Query.QueryDatabase(msiPath, new[] { "Component" });

Assert.Equal(5, results.Length);
Assert.Contains(results, component => component.Contains("hklm") && component.Contains("8A4C3648-26AF-5E7E-B64B-D97961856FA4", StringComparison.InvariantCultureIgnoreCase));
Assert.Contains(results, component => component.Contains("hkcr") && component.Contains("B40FBCDB-D01C-575F-9030-7B95813A419C", StringComparison.InvariantCultureIgnoreCase));
Assert.Contains(results, component => component.Contains("hkcu") && component.Contains("04EB5AB4-FFF7-53D5-A913-1C146FC61EF2", StringComparison.InvariantCultureIgnoreCase));
Assert.Contains(results, component => component.Contains("hku") && component.Contains("CC64CDBB-077E-532B-9F95-A1E1EB162875", StringComparison.InvariantCultureIgnoreCase));
Assert.Contains(results, component => component.Contains("file") && component.Contains("C207E21E-B6F4-537A-A8AB-620DD88646D6", StringComparison.InvariantCultureIgnoreCase));
}
}

[Fact]
public void PopulatesCreateFolderTableForNullKeypathComponents()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="WiX3CompatibleGuid" Codepage="1252" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="no" InstallerVersion="200" Scope="perMachine">

<MajorUpgrade DowngradeErrorMessage="Dont care" />

<Feature Id="ProductFeature" Title="Title">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Package>

<Fragment>
<StandardDirectory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WiX3CompatibleGuid" />
</StandardDirectory>
</Fragment>
</Wix>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="TARGETDIR">
<!-- Expecting {8BAF5399-2FD2-50B6-ABDA-98FB3A5BB148} -->
<Component Id="WiX3CompatibleGuid" WiX3CompatibleGuid="yes" Bitness="always32" Condition="x=y">
<RegistryValue Root="HKLM" Key="SOFTWARE\WiX3CompatiblityCheck" Name="Test" Value="test value" />
</Component>

<!-- Expecting *not* {8BAF5399-2FD2-50B6-ABDA-98FB3A5BB148} -->
<Component Id="WiX4CompatibleGuid" Bitness="always32" Condition="x=z">
<RegistryValue Root="HKLM" Key="SOFTWARE\WiX3CompatiblityCheck" Name="Test" Value="test value" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="WiX3CompatibleGuid" Codepage="1252" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="no" InstallerVersion="200" Scope="perMachine">

<MajorUpgrade DowngradeErrorMessage="Dont care" />

<Feature Id="ProductFeature" Title="Title">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Package>

<Fragment>
<StandardDirectory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WiX4CompatibleGuid" />
</StandardDirectory>
</Fragment>
</Wix>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="TARGETDIR">

<!-- Expecting {8A4C3648-26AF-5E7E-B64B-D97961856FA4} -->
<Component Directory='TARGETDIR' Bitness="always32" Id="hklm">
<RegistryValue Root="HKLM" Key="SOFTWARE\WiX3CompatiblityCheck" Name="Test" Value="test value" Type="string"/>
</Component>

<!-- Expecting {B40FBCDB-D01C-575F-9030-7B95813A419C} -->
<Component Directory='TARGETDIR' Bitness="always32" Id="hkcr">
<RegistryValue Root="HKCR" Key="SOFTWARE\WiX3CompatiblityCheck" Name="Test" Value="test value" Type="string"/>
</Component>

<!-- Expecting {04EB5AB4-FFF7-53D5-A913-1C146FC61EF2} -->
<Component Directory='TARGETDIR' Bitness="always32" Id="hkcu">
<RegistryValue Root="HKCU" Key="SOFTWARE\WiX3CompatiblityCheck" Name="Test" Value="test value" Type="string"/>
</Component>

<!-- Expecting {C207E21E-B6F4-537A-A8AB-620DD88646D6} -->
<Component Directory='TARGETDIR' Bitness="always32" Id="hku">
<RegistryValue Root="HKU" Key="SOFTWARE\WiX3CompatiblityCheck" Name="Test" Value="test value" Type="string"/>
</Component>

<!-- Expecting {65C9D9DC-1485-5F56-AED3-E14B7ACD17BE} -->
<Component Directory='INSTALLFOLDER' Bitness="always32" Id="file">
<File Source='$(sys.SOURCEFILEPATH)' Name='test.wxs'/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>

0 comments on commit 08d0115

Please sign in to comment.