aboutsummaryrefslogtreecommitdiff
path: root/src/ext/NetFx/wixext
diff options
context:
space:
mode:
authorStefanStojanovic <StefanStojanovic@users.noreply.github.com>2022-10-25 22:40:36 +0200
committerGitHub <noreply@github.com>2022-10-25 20:40:36 +0000
commit321c30138c82390ea5ad6b0a612dff294203a877 (patch)
tree2f27ca578d9b162eac11f0c8bee460b17138b531 /src/ext/NetFx/wixext
parent98080672cdbbde00ea40a96c1ce38e8a52f24fee (diff)
downloadwix-321c30138c82390ea5ad6b0a612dff294203a877.tar.gz
wix-321c30138c82390ea5ad6b0a612dff294203a877.tar.bz2
wix-321c30138c82390ea5ad6b0a612dff294203a877.zip
Add NetFx .NET compatibility check for MSI (#262)
Adds new custom element in NetFx extension for running NetCoreCheck.exe tool from within the MSI installer - `<netfx:DotNetCompatibilityCheck />`. The checks are run before evaluating launch conditions, so their results can be used in those conditions. There is no limitation on the number of checks that can be run, so installer may query various runtimes on different platforms and versions and with different roll forward policies. Fixes https://github.com/wixtoolset/issues/issues/6264
Diffstat (limited to 'src/ext/NetFx/wixext')
-rw-r--r--src/ext/NetFx/wixext/NetFxCompiler.cs213
-rw-r--r--src/ext/NetFx/wixext/NetFxExtensionData.cs2
-rw-r--r--src/ext/NetFx/wixext/NetfxTableDefinitions.cs16
-rw-r--r--src/ext/NetFx/wixext/Symbols/NetFxDotNetCompatibilityCheckSymbol.cs79
-rw-r--r--src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs6
5 files changed, 314 insertions, 2 deletions
diff --git a/src/ext/NetFx/wixext/NetFxCompiler.cs b/src/ext/NetFx/wixext/NetFxCompiler.cs
index 739618e9..f3c91918 100644
--- a/src/ext/NetFx/wixext/NetFxCompiler.cs
+++ b/src/ext/NetFx/wixext/NetFxCompiler.cs
@@ -40,7 +40,6 @@ namespace WixToolset.Netfx
40 break; 40 break;
41 } 41 }
42 break; 42 break;
43 case "Bundle":
44 case "Fragment": 43 case "Fragment":
45 switch (element.Name.LocalName) 44 switch (element.Name.LocalName)
46 { 45 {
@@ -50,8 +49,45 @@ namespace WixToolset.Netfx
50 case "DotNetCoreSearchRef": 49 case "DotNetCoreSearchRef":
51 this.ParseDotNetCoreSearchRefElement(intermediate, section, element); 50 this.ParseDotNetCoreSearchRefElement(intermediate, section, element);
52 break; 51 break;
52 case "DotNetCompatibilityCheck":
53 this.ParseDotNetCompatibilityCheckElement(intermediate, section, element);
54 break;
55 case "DotNetCompatibilityCheckRef":
56 this.ParseDotNetCompatibilityCheckRefElement(intermediate, section, element);
57 break;
58 default:
59 this.ParseHelper.UnexpectedElement(parentElement, element);
60 break;
61 }
62 break;
63 case "Bundle":
64 switch (element.Name.LocalName)
65 {
66 case "DotNetCoreSearch":
67 this.ParseDotNetCoreSearchElement(intermediate, section, element);
68 break;
69 case "DotNetCoreSearchRef":
70 this.ParseDotNetCoreSearchRefElement(intermediate, section, element);
71 break;
72 default:
73 this.ParseHelper.UnexpectedElement(parentElement, element);
74 break;
75 }
76 break;
77 case "Package":
78 case "Module":
79 switch (element.Name.LocalName)
80 {
81 case "DotNetCompatibilityCheck":
82 this.ParseDotNetCompatibilityCheckElement(intermediate, section, element);
83 break;
84 case "DotNetCompatibilityCheckRef":
85 this.ParseDotNetCompatibilityCheckRefElement(intermediate, section, element);
86 break;
87 default:
88 this.ParseHelper.UnexpectedElement(parentElement, element);
89 break;
53 } 90 }
54
55 break; 91 break;
56 default: 92 default:
57 this.ParseHelper.UnexpectedElement(parentElement, element); 93 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -325,5 +361,178 @@ namespace WixToolset.Netfx
325 }); 361 });
326 } 362 }
327 } 363 }
364
365 /// <summary>
366 /// Parses a DotNetCompatibilityCheck element.
367 /// </summary>
368 /// <param name="element">The element to parse.</param>
369 private void ParseDotNetCompatibilityCheckElement(Intermediate intermediate, IntermediateSection section, XElement element)
370 {
371 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
372 Identifier id = null;
373 string property = null;
374 string runtimeType = null;
375 string platform = null;
376 string version = null;
377 string rollForward = "Minor";
378
379 foreach (var attrib in element.Attributes())
380 {
381 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
382 {
383 switch (attrib.Name.LocalName)
384 {
385 case "Id":
386 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
387 break;
388 case "Property":
389 property = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
390 break;
391 case "RuntimeType":
392 runtimeType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
393 switch (runtimeType.ToLower())
394 {
395 case "aspnet":
396 runtimeType = "Microsoft.AspNetCore.App";
397 break;
398 case "desktop":
399 runtimeType = "Microsoft.WindowsDesktop.App";
400 break;
401 case "core":
402 runtimeType = "Microsoft.NETCore.App";
403 break;
404 default:
405 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, runtimeType, "aspnet", "desktop", "core"));
406 break;
407 }
408 break;
409 case "Platform":
410 platform = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
411 switch (platform.ToLower())
412 {
413 case "x86":
414 case "x64":
415 case "arm64":
416 platform = platform.ToLower();
417 break;
418 default:
419 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, platform, "x86", "x64", "arm64"));
420 break;
421 }
422 break;
423 case "Version":
424 version = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib);
425 break;
426 case "RollForward":
427 rollForward = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
428 switch (rollForward.ToLower())
429 {
430 case "latestmajor":
431 rollForward = "LatestMajor";
432 break;
433 case "major":
434 rollForward = "Major";
435 break;
436 case "latestminor":
437 rollForward = "LatestMinor";
438 break;
439 case "minor":
440 rollForward = "Minor";
441 break;
442 case "latestpatch":
443 rollForward = "LatestPatch";
444 break;
445 case "disable":
446 rollForward = "Disable";
447 break;
448 default:
449 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, rollForward, "latestmajor", "major", "latestminor", "minor", "latestpatch", "disable"));
450 break;
451 }
452 break;
453 default:
454 this.ParseHelper.UnexpectedAttribute(element, attrib);
455 break;
456 }
457 }
458 else
459 {
460 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
461 }
462 }
463
464 if (null == id)
465 {
466 id = this.ParseHelper.CreateIdentifier("ndncc", property, runtimeType, platform, version);
467 }
468
469 if (String.IsNullOrEmpty(property))
470 {
471 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Property"));
472 }
473
474 if (String.IsNullOrEmpty(runtimeType))
475 {
476 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "RuntimeType"));
477 }
478
479 if (String.IsNullOrEmpty(platform))
480 {
481 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Platform"));
482 }
483
484 if (String.IsNullOrEmpty(version))
485 {
486 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Version"));
487 }
488
489 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
490
491 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4NetFxDotNetCompatibilityCheck", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
492
493 if (!this.Messaging.EncounteredError)
494 {
495 section.AddSymbol(new NetFxDotNetCompatibilityCheckSymbol(sourceLineNumbers, id)
496 {
497 RuntimeType = runtimeType,
498 Platform = platform,
499 Version = version,
500 RollForward = rollForward,
501 Property = property,
502 });
503 }
504 }
505
506 /// <summary>
507 /// Parses a DotNetCompatibilityCheckRef element.
508 /// </summary>
509 /// <param name="element">The element to parse.</param>
510 private void ParseDotNetCompatibilityCheckRefElement(Intermediate intermediate, IntermediateSection section, XElement element)
511 {
512 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
513
514 foreach (var attrib in element.Attributes())
515 {
516 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
517 {
518 switch (attrib.Name.LocalName)
519 {
520 case "Id":
521 var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
522 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck, refId);
523 break;
524 default:
525 this.ParseHelper.UnexpectedAttribute(element, attrib);
526 break;
527 }
528 }
529 else
530 {
531 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
532 }
533 }
534
535 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
536 }
328 } 537 }
329} 538}
diff --git a/src/ext/NetFx/wixext/NetFxExtensionData.cs b/src/ext/NetFx/wixext/NetFxExtensionData.cs
index 61d618cf..8dd9e003 100644
--- a/src/ext/NetFx/wixext/NetFxExtensionData.cs
+++ b/src/ext/NetFx/wixext/NetFxExtensionData.cs
@@ -10,6 +10,8 @@ namespace WixToolset.Netfx
10 /// </summary> 10 /// </summary>
11 public sealed class NetfxExtensionData : BaseExtensionData 11 public sealed class NetfxExtensionData : BaseExtensionData
12 { 12 {
13 public override string DefaultCulture => "en-US";
14
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 15 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 { 16 {
15 symbolDefinition = NetfxSymbolDefinitions.ByName(name); 17 symbolDefinition = NetfxSymbolDefinitions.ByName(name);
diff --git a/src/ext/NetFx/wixext/NetfxTableDefinitions.cs b/src/ext/NetFx/wixext/NetfxTableDefinitions.cs
index 57e35323..6be1abe7 100644
--- a/src/ext/NetFx/wixext/NetfxTableDefinitions.cs
+++ b/src/ext/NetFx/wixext/NetfxTableDefinitions.cs
@@ -22,9 +22,25 @@ namespace WixToolset.Netfx
22 symbolIdIsPrimaryKey: true 22 symbolIdIsPrimaryKey: true
23 ); 23 );
24 24
25 public static readonly TableDefinition NetFxDotNetCompatibilityCheck = new TableDefinition(
26 "Wix4NetFxDotNetCheck",
27 NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck,
28 new[]
29 {
30 new ColumnDefinition("NetFxDotNetCompatibilityCheck", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column),
31 new ColumnDefinition("RuntimeType", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "The type of .NET runtime being checked for. Possible values: aspnet, desktop and core", modularizeType: ColumnModularizeType.Column),
32 new ColumnDefinition("Platform", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Sets the platform for the .NET runtime being checked for. Possible values: x86, x64 and arm64", modularizeType: ColumnModularizeType.Column),
33 new ColumnDefinition("Version", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Version, description: "The version of the .NET runtime being checked for (e.g. 3.1.10, 5.0.1).", modularizeType: ColumnModularizeType.Column),
34 new ColumnDefinition("RollForward", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Sets the roll-forward policy that the application is using. Possible values: latestmajor, major, latestminor, minor, latestpatch and disable", modularizeType: ColumnModularizeType.Column),
35 new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of the property in which to place the result of the check.", modularizeType: ColumnModularizeType.Column),
36 },
37 symbolIdIsPrimaryKey: true
38 );
39
25 public static readonly TableDefinition[] All = new[] 40 public static readonly TableDefinition[] All = new[]
26 { 41 {
27 NetFxNativeImage, 42 NetFxNativeImage,
43 NetFxDotNetCompatibilityCheck
28 }; 44 };
29 } 45 }
30} 46}
diff --git a/src/ext/NetFx/wixext/Symbols/NetFxDotNetCompatibilityCheckSymbol.cs b/src/ext/NetFx/wixext/Symbols/NetFxDotNetCompatibilityCheckSymbol.cs
new file mode 100644
index 00000000..a46cf17f
--- /dev/null
+++ b/src/ext/NetFx/wixext/Symbols/NetFxDotNetCompatibilityCheckSymbol.cs
@@ -0,0 +1,79 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Netfx
4{
5 using WixToolset.Data;
6 using WixToolset.Netfx.Symbols;
7
8 public static partial class NetfxSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition NetFxDotNetCompatibilityCheck = new IntermediateSymbolDefinition(
11 NetfxSymbolDefinitionType.NetFxDotNetCompatibilityCheck.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(NetFxDotNetCompatibilityCheckSymbollFields.RuntimeType), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(NetFxDotNetCompatibilityCheckSymbollFields.Platform), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(NetFxDotNetCompatibilityCheckSymbollFields.Version), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(NetFxDotNetCompatibilityCheckSymbollFields.RollForward), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(NetFxDotNetCompatibilityCheckSymbollFields.Property), IntermediateFieldType.String),
19 },
20 typeof(NetFxDotNetCompatibilityCheckSymbol));
21 }
22}
23
24namespace WixToolset.Netfx.Symbols
25{
26 using WixToolset.Data;
27
28 public enum NetFxDotNetCompatibilityCheckSymbollFields
29 {
30 RuntimeType,
31 Platform,
32 Version,
33 RollForward,
34 Property,
35 }
36
37 public class NetFxDotNetCompatibilityCheckSymbol : IntermediateSymbol
38 {
39 public NetFxDotNetCompatibilityCheckSymbol() : base(NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck, null, null)
40 {
41 }
42
43 public NetFxDotNetCompatibilityCheckSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck, sourceLineNumber, id)
44 {
45 }
46
47 public IntermediateField this[NetFxDotNetCompatibilityCheckSymbollFields index] => this.Fields[(int)index];
48
49 public string RuntimeType
50 {
51 get => this.Fields[(int)NetFxDotNetCompatibilityCheckSymbollFields.RuntimeType].AsString();
52 set => this.Set((int)NetFxDotNetCompatibilityCheckSymbollFields.RuntimeType, value);
53 }
54
55 public string Platform
56 {
57 get => this.Fields[(int)NetFxDotNetCompatibilityCheckSymbollFields.Platform].AsString();
58 set => this.Set((int)NetFxDotNetCompatibilityCheckSymbollFields.Platform, value);
59 }
60
61 public string Version
62 {
63 get => this.Fields[(int)NetFxDotNetCompatibilityCheckSymbollFields.Version].AsString();
64 set => this.Set((int)NetFxDotNetCompatibilityCheckSymbollFields.Version, value);
65 }
66
67 public string RollForward
68 {
69 get => this.Fields[(int)NetFxDotNetCompatibilityCheckSymbollFields.RollForward].AsString();
70 set => this.Set((int)NetFxDotNetCompatibilityCheckSymbollFields.RollForward, value);
71 }
72
73 public string Property
74 {
75 get => this.Fields[(int)NetFxDotNetCompatibilityCheckSymbollFields.Property].AsString();
76 set => this.Set((int)NetFxDotNetCompatibilityCheckSymbollFields.Property, value);
77 }
78 }
79}
diff --git a/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs b/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs
index 862eba16..ad729dd4 100644
--- a/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs
+++ b/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs
@@ -10,10 +10,13 @@ namespace WixToolset.Netfx
10 { 10 {
11 NetFxNativeImage, 11 NetFxNativeImage,
12 NetFxNetCoreSearch, 12 NetFxNetCoreSearch,
13 NetFxDotNetCompatibilityCheck
13 } 14 }
14 15
15 public static partial class NetfxSymbolDefinitions 16 public static partial class NetfxSymbolDefinitions
16 { 17 {
18 public static readonly Version Version = new Version("4.0.0");
19
17 public static IntermediateSymbolDefinition ByName(string name) 20 public static IntermediateSymbolDefinition ByName(string name)
18 { 21 {
19 if (!Enum.TryParse(name, out NetfxSymbolDefinitionType type)) 22 if (!Enum.TryParse(name, out NetfxSymbolDefinitionType type))
@@ -33,6 +36,9 @@ namespace WixToolset.Netfx
33 36
34 case NetfxSymbolDefinitionType.NetFxNetCoreSearch: 37 case NetfxSymbolDefinitionType.NetFxNetCoreSearch:
35 return NetfxSymbolDefinitions.NetFxNetCoreSearch; 38 return NetfxSymbolDefinitions.NetFxNetCoreSearch;
39
40 case NetfxSymbolDefinitionType.NetFxDotNetCompatibilityCheck:
41 return NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck;
36 42
37 default: 43 default:
38 throw new ArgumentOutOfRangeException(nameof(type)); 44 throw new ArgumentOutOfRangeException(nameof(type));