@joebigelow / wix / commits / 321c3013

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

StefanStojanovic committed Oct 25, 2022 at 22:40 UTC 321c30138c82390ea5ad6b0a612dff294203a877
13 files changed +496 -3
src/ext/NetFx/ca/netfxca.cpp
+144
@@ -36,6 +36,10 @@ LPCWSTR vcsNgenStrongName =
36 L"SELECT `Name`,`Value` FROM `MsiAssemblyName` WHERE `Component_`=?";
37 enum eNgenStrongName { ngsnName = 1, ngsnValue };
38
39 +LPCWSTR vscDotNetCompatibilityCheckQuery =
40 + L"SELECT `Platform`, `RuntimeType`, `Version`, `RollForward`, `Property` FROM `Wix4NetFxDotNetCheck`";
41 +enum eDotNetCompatibilityCheckQuery { platform = 1, runtimeType, version, rollForward, property };
42 +
43 // Searches subdirectories of the given path for the highest version of ngen.exe available
44 static HRESULT GetNgenVersion(
45 __in LPWSTR pwzParentPath,
@@ -500,6 +504,15 @@ extern "C" UINT __stdcall SchedNetFx(
504 hr = WcaInitialize(hInstall, "SchedNetFx");
505 ExitOnFailure(hr, "failed to initialize");
506
507 + // If Wix4NetFxNativeImage table doesn't exist skip the rest of this custom action
508 + hr = WcaTableExists(L"Wix4NetFxNativeImage");
509 + if (S_FALSE == hr)
510 + {
511 + hr = S_OK;
512 + ExitFunction();
513 + }
514 + ExitOnFailure(hr, "failed to check if table Wix4NetFxNativeImage exists");
515 +
516 hr = GetNgenPath(&pwz32Ngen, FALSE);
517 f32NgenExeExists = SUCCEEDED(hr);
518 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
@@ -879,3 +892,134 @@ LExit:
892 return WcaFinalize(er);
893 }
894
895 +/******************************************************************
896 + DotNetCompatibilityCheck - entry point for NetFx Custom Action
897 +
898 +*******************************************************************/
899 +extern "C" UINT __stdcall DotNetCompatibilityCheck(
900 + __in MSIHANDLE hInstall
901 + )
902 +{
903 +// AssertSz(FALSE, "debug DotNetCompatibilityCheck");
904 +
905 + HRESULT hr = S_OK;
906 + UINT er = ERROR_SUCCESS;
907 +
908 + PMSIHANDLE hView = NULL;
909 + PMSIHANDLE hRec = NULL;
910 + LPWSTR pwzPlatform = NULL;
911 + LPWSTR pwzNetCoreCheckBinaryId = NULL;
912 + LPWSTR pwzNetCoreCheckDirectoryName = NULL;
913 + LPWSTR pwzNetCoreCheckDirectoryPath = NULL;
914 + LPWSTR pwzNetCoreCheckFilePath = NULL;
915 + LPWSTR pwzRuntimeType = NULL;
916 + LPWSTR pwzVersion = NULL;
917 + LPWSTR pwzRollForward = NULL;
918 + LPWSTR pwzProperty = NULL;
919 + LPWSTR pwzCommandLine = NULL;
920 + HANDLE hProcess = NULL;
921 + DWORD dwExitCode = 0;
922 +
923 + // Initialize
924 + hr = WcaInitialize(hInstall, "DotNetCompatibilityCheck");
925 + ExitOnFailure(hr, "failed to initialize");
926 +
927 + // If Wix4NetFxDotNetCheck table doesn't exist skip the rest of this custom action
928 + hr = WcaTableExists(L"Wix4NetFxDotNetCheck");
929 + if (S_FALSE == hr)
930 + {
931 + hr = S_OK;
932 + ExitFunction();
933 + }
934 + ExitOnFailure(hr, "failed to check if table Wix4NetFxDotNetCheck exists");
935 +
936 + // Open view on .NET compatibility check table
937 + hr = WcaOpenExecuteView(vscDotNetCompatibilityCheckQuery, &hView);
938 + ExitOnFailure(hr, "failed to open view on Wix4NetFxDotNetCheck table");
939 +
940 + // Go through all records and run NetCorCheck.exe for each
941 + while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
942 + {
943 + // Extract NetCoreCheck.exe for platform to temp directory
944 + hr = WcaGetRecordString(hRec, platform, &pwzPlatform);
945 + ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.Platform");
946 +
947 + hr = StrAllocFormatted(&pwzNetCoreCheckBinaryId, L"Wix4NetCheck_%ls", pwzPlatform);
948 + ExitOnFailure(hr, "failed to get NetCoreCheck binary id for platform %ls", pwzPlatform);
949 +
950 + hr = GuidCreate(&pwzNetCoreCheckDirectoryName);
951 + ExitOnFailure(hr, "failed to set NetCoreCheck directory name");
952 +
953 + hr = PathCreateTempDirectory(NULL, pwzNetCoreCheckDirectoryName, 1, &pwzNetCoreCheckDirectoryPath);
954 + ExitOnFailure(hr, "failed to make NetCoreCheck directory path for name %ls", pwzNetCoreCheckDirectoryName);
955 +
956 + hr = StrAllocFormatted(&pwzNetCoreCheckFilePath, L"%lsNetCoreCheck.exe", pwzNetCoreCheckDirectoryPath);
957 + ExitOnFailure(hr, "failed to set NetCoreCheck file path for directory %ls", pwzNetCoreCheckDirectoryPath);
958 +
959 + hr = WcaExtractBinaryToFile(pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath);
960 + ExitOnFailure(hr, "failed to extract NetCoreCheck from binary '%ls' to file %ls", pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath);
961 +
962 + // Read all NetCoreCheck.exe parameters and property
963 + hr = WcaGetRecordString(hRec, runtimeType, &pwzRuntimeType);
964 + ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.RuntimeType");
965 +
966 + hr = WcaGetRecordString(hRec, version, &pwzVersion);
967 + ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.Version");
968 +
969 + hr = WcaGetRecordString(hRec, rollForward, &pwzRollForward);
970 + ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.RollForward");
971 +
972 + hr = WcaGetRecordString(hRec, property, &pwzProperty);
973 + ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.Property");
974 +
975 + // Run NetCoreCheck.exe and store its result in property
976 + hr = StrAllocFormatted(&pwzCommandLine, L"-n %ls -v %ls -r %ls", pwzRuntimeType, pwzVersion, pwzRollForward);
977 + ExitOnFailure(hr, "failed to set NetCoreCheck command line");
978 + WcaLog(LOGMSG_VERBOSE, "Command: %ls %ls", pwzNetCoreCheckFilePath, pwzCommandLine);
979 +
980 + hr = ProcExec(pwzNetCoreCheckFilePath, pwzCommandLine, SW_HIDE, &hProcess);
981 + ExitOnFailure(hr, "failed to run NetCoreCheck from binary '%ls' with command line: %ls %ls", pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath, pwzCommandLine);
982 +
983 + hr = ProcWaitForCompletion(hProcess, INFINITE, &dwExitCode);
984 + ExitOnFailure(hr, "failed to finish NetCoreCheck from binary '%ls' with command line: %ls %ls", pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath, pwzCommandLine);
985 + WcaLog(LOGMSG_VERBOSE, "Exit code: %lu", dwExitCode);
986 + ReleaseHandle(hProcess);
987 +
988 + hr = WcaSetIntProperty(pwzProperty, dwExitCode);
989 + ExitOnFailure(hr, "failed to set NetCoreCheck result in %ls", pwzProperty);
990 +
991 + // Delete extracted NetCoreCheck.exe
992 + DirEnsureDelete(pwzNetCoreCheckDirectoryPath, TRUE, TRUE);
993 + }
994 + if (E_NOMOREITEMS == hr)
995 + {
996 + hr = S_OK;
997 + }
998 + ExitOnFailure(hr, "failed while looping through all dot net compatibility checks");
999 +
1000 +LExit:
1001 + // Delete extracted NetCoreCheck.exe
1002 + if (NULL != pwzNetCoreCheckDirectoryPath)
1003 + {
1004 + DirEnsureDelete(pwzNetCoreCheckDirectoryPath, TRUE, TRUE);
1005 + }
1006 +
1007 + // Release allocated resources
1008 + ReleaseStr(pwzPlatform);
1009 + ReleaseStr(pwzNetCoreCheckBinaryId);
1010 + ReleaseStr(pwzNetCoreCheckDirectoryName);
1011 + ReleaseStr(pwzNetCoreCheckDirectoryPath);
1012 + ReleaseStr(pwzNetCoreCheckFilePath);
1013 + ReleaseStr(pwzRuntimeType);
1014 + ReleaseStr(pwzVersion);
1015 + ReleaseStr(pwzRollForward);
1016 + ReleaseStr(pwzProperty);
1017 + ReleaseStr(pwzCommandLine);
1018 + ReleaseHandle(hProcess);
1019 +
1020 + if (FAILED(hr))
1021 + {
1022 + er = ERROR_INSTALL_FAILURE;
1023 + }
1024 + return WcaFinalize(er);
1025 +}
src/ext/NetFx/ca/netfxca.def
+1
@@ -6,3 +6,4 @@ LIBRARY "netfxca"
6 EXPORTS
7 SchedNetFx
8 ExecNetFx
9 + DotNetCompatibilityCheck
src/ext/NetFx/ca/netfxca.vcxproj
+1 -1
@@ -42,7 +42,7 @@
42 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
43
44 <PropertyGroup>
45 - <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries>
45 + <ProjectAdditionalLinkLibraries>msi.lib;rpcrt4.lib</ProjectAdditionalLinkLibraries>
46 </PropertyGroup>
47
48 <ItemGroup>
src/ext/NetFx/ca/precomp.h
+3
@@ -10,6 +10,9 @@
10 #include "fileutil.h"
11 #include "strutil.h"
12 #include "pathutil.h"
13 +#include "procutil.h"
14 +#include "dirutil.h"
15 +#include "guidutil.h"
16
17 #include "caDecor.h"
18 #include "cost.h"
src/ext/NetFx/test/WixToolsetTest.Netfx/NetfxExtensionFixture.cs
+12
@@ -85,7 +85,11 @@ namespace WixToolsetTest.Netfx
85 var results = build.BuildAndQuery(Build, "Binary", "CustomAction", "Wix4NetFxNativeImage");
86 WixAssert.CompareLineByLine(new[]
87 {
88 + "Binary:Wix4NetCheck_arm64\t[Binary data]",
89 + "Binary:Wix4NetCheck_x64\t[Binary data]",
90 + "Binary:Wix4NetCheck_x86\t[Binary data]",
91 "Binary:Wix4NetFxCA_X86\t[Binary data]",
92 + "CustomAction:Wix4NetFxDotNetCompatibilityCheck_X86\t1\tWix4NetFxCA_X86\tDotNetCompatibilityCheck\t",
93 "CustomAction:Wix4NetFxExecuteNativeImageCommitInstall_X86\t3649\tWix4NetFxCA_X86\tExecNetFx\t",
94 "CustomAction:Wix4NetFxExecuteNativeImageCommitUninstall_X86\t3649\tWix4NetFxCA_X86\tExecNetFx\t",
95 "CustomAction:Wix4NetFxExecuteNativeImageInstall_X86\t3137\tWix4NetFxCA_X86\tExecNetFx\t",
@@ -104,7 +108,11 @@ namespace WixToolsetTest.Netfx
108 var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "Wix4NetFxNativeImage");
109 WixAssert.CompareLineByLine(new[]
110 {
111 + "Binary:Wix4NetCheck_arm64\t[Binary data]",
112 + "Binary:Wix4NetCheck_x64\t[Binary data]",
113 + "Binary:Wix4NetCheck_x86\t[Binary data]",
114 "Binary:Wix4NetFxCA_X64\t[Binary data]",
115 + "CustomAction:Wix4NetFxDotNetCompatibilityCheck_X64\t1\tWix4NetFxCA_X64\tDotNetCompatibilityCheck\t",
116 "CustomAction:Wix4NetFxExecuteNativeImageCommitInstall_X64\t3649\tWix4NetFxCA_X64\tExecNetFx\t",
117 "CustomAction:Wix4NetFxExecuteNativeImageCommitUninstall_X64\t3649\tWix4NetFxCA_X64\tExecNetFx\t",
118 "CustomAction:Wix4NetFxExecuteNativeImageInstall_X64\t3137\tWix4NetFxCA_X64\tExecNetFx\t",
@@ -123,7 +131,11 @@ namespace WixToolsetTest.Netfx
131 var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction", "Wix4NetFxNativeImage");
132 WixAssert.CompareLineByLine(new[]
133 {
134 + "Binary:Wix4NetCheck_arm64\t[Binary data]",
135 + "Binary:Wix4NetCheck_x64\t[Binary data]",
136 + "Binary:Wix4NetCheck_x86\t[Binary data]",
137 "Binary:Wix4NetFxCA_A64\t[Binary data]",
138 + "CustomAction:Wix4NetFxDotNetCompatibilityCheck_A64\t1\tWix4NetFxCA_A64\tDotNetCompatibilityCheck\t",
139 "CustomAction:Wix4NetFxExecuteNativeImageCommitInstall_A64\t3649\tWix4NetFxCA_A64\tExecNetFx\t",
140 "CustomAction:Wix4NetFxExecuteNativeImageCommitUninstall_A64\t3649\tWix4NetFxCA_A64\tExecNetFx\t",
141 "CustomAction:Wix4NetFxExecuteNativeImageInstall_A64\t3137\tWix4NetFxCA_A64\tExecNetFx\t",
src/ext/NetFx/wixext/NetFxCompiler.cs
+211 -2
@@ -40,7 +40,6 @@ namespace WixToolset.Netfx
40 break;
41 }
42 break;
43 - case "Bundle":
43 case "Fragment":
44 switch (element.Name.LocalName)
45 {
@@ -50,8 +49,45 @@ namespace WixToolset.Netfx
49 case "DotNetCoreSearchRef":
50 this.ParseDotNetCoreSearchRefElement(intermediate, section, element);
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;
90 }
54 -
91 break;
92 default:
93 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -325,5 +361,178 @@ namespace WixToolset.Netfx
361 });
362 }
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 + }
537 }
538 }
src/ext/NetFx/wixext/NetFxExtensionData.cs
+2
@@ -10,6 +10,8 @@ namespace WixToolset.Netfx
10 /// </summary>
11 public sealed class NetfxExtensionData : BaseExtensionData
12 {
13 + public override string DefaultCulture => "en-US";
14 +
15 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
16 {
17 symbolDefinition = NetfxSymbolDefinitions.ByName(name);
src/ext/NetFx/wixext/NetfxTableDefinitions.cs
+16
@@ -22,9 +22,25 @@ namespace WixToolset.Netfx
22 symbolIdIsPrimaryKey: true
23 );
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 +
40 public static readonly TableDefinition[] All = new[]
41 {
42 NetFxNativeImage,
43 + NetFxDotNetCompatibilityCheck
44 };
45 }
46 }
src/ext/NetFx/wixext/Symbols/NetFxDotNetCompatibilityCheckSymbol.cs new
+79
@@ -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 +
3 +namespace 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 +
24 +namespace 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 +}
src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs
+6
@@ -10,10 +10,13 @@ namespace WixToolset.Netfx
10 {
11 NetFxNativeImage,
12 NetFxNetCoreSearch,
13 + NetFxDotNetCompatibilityCheck
14 }
15
16 public static partial class NetfxSymbolDefinitions
17 {
18 + public static readonly Version Version = new Version("4.0.0");
19 +
20 public static IntermediateSymbolDefinition ByName(string name)
21 {
22 if (!Enum.TryParse(name, out NetfxSymbolDefinitionType type))
@@ -33,6 +36,9 @@ namespace WixToolset.Netfx
36
37 case NetfxSymbolDefinitionType.NetFxNetCoreSearch:
38 return NetfxSymbolDefinitions.NetFxNetCoreSearch;
39 +
40 + case NetfxSymbolDefinitionType.NetFxDotNetCompatibilityCheck:
41 + return NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck;
42
43 default:
44 throw new ArgumentOutOfRangeException(nameof(type));
src/ext/NetFx/wixlib/NetFxExtension_Platform.wxi
+9
@@ -10,6 +10,7 @@
10 <CustomAction Id="$(var.Prefix)NetFxExecuteNativeImageCommitInstall$(var.Suffix)" DllEntry="ExecNetFx" Execute="commit" Impersonate="no" Return="ignore" SuppressModularization="yes" BinaryRef="$(var.Prefix)NetFxCA$(var.Suffix)" />
11 <CustomAction Id="$(var.Prefix)NetFxExecuteNativeImageUninstall$(var.Suffix)" DllEntry="ExecNetFx" Execute="deferred" Impersonate="no" Return="ignore" SuppressModularization="yes" BinaryRef="$(var.Prefix)NetFxCA$(var.Suffix)" />
12 <CustomAction Id="$(var.Prefix)NetFxExecuteNativeImageCommitUninstall$(var.Suffix)" DllEntry="ExecNetFx" Execute="commit" Impersonate="no" Return="ignore" SuppressModularization="yes" BinaryRef="$(var.Prefix)NetFxCA$(var.Suffix)" />
13 + <CustomAction Id="$(var.Prefix)NetFxDotNetCompatibilityCheck$(var.Suffix)" DllEntry="DotNetCompatibilityCheck" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)NetFxCA$(var.Suffix)" />
14
15 <InstallExecuteSequence>
16 <Custom Action="$(var.Prefix)NetFxScheduleNativeImage$(var.Suffix)" Before="InstallFiles" Overridable="yes" />
@@ -17,11 +18,19 @@
18 <Custom Action="$(var.Prefix)NetFxExecuteNativeImageUninstall$(var.Suffix)" After="$(var.Prefix)NetFxExecuteNativeImageCommitUninstall$(var.Suffix)" Overridable="yes" Condition="RollbackDisabled = 1" />
19 <Custom Action="$(var.Prefix)NetFxExecuteNativeImageCommitInstall$(var.Suffix)" After="$(var.Prefix)NetFxExecuteNativeImageUninstall$(var.Suffix)" Overridable="yes" Condition="RollbackDisabled &lt;&gt; 1" />
20 <Custom Action="$(var.Prefix)NetFxExecuteNativeImageInstall$(var.Suffix)" After="$(var.Prefix)NetFxExecuteNativeImageCommitInstall$(var.Suffix)" Overridable="yes" Condition="RollbackDisabled = 1" />
21 + <Custom Action="$(var.Prefix)NetFxDotNetCompatibilityCheck$(var.Suffix)" Before="LaunchConditions" Overridable="yes" />
22 </InstallExecuteSequence>
23 +
24 + <InstallUISequence>
25 + <Custom Action="$(var.Prefix)NetFxDotNetCompatibilityCheck$(var.Suffix)" Before="LaunchConditions" Overridable="yes" />
26 + </InstallUISequence>
27 </Fragment>
28
29 <!-- NetFx Custom Action DLL Definitions -->
30 <Fragment>
31 <Binary Id="$(var.Prefix)NetFxCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))netfxca.dll" />
32 + <Binary Id="$(var.Prefix)NetCheck_x86" SourceFile="!(bindpath.x86)NetCoreCheck.exe" />
33 + <Binary Id="$(var.Prefix)NetCheck_x64" SourceFile="!(bindpath.x64)NetCoreCheck.exe" />
34 + <Binary Id="$(var.Prefix)NetCheck_arm64" SourceFile="!(bindpath.arm64)NetCoreCheck.exe" />
35 </Fragment>
36 </Include>
src/ext/NetFx/wixlib/netfx.wixproj
+6
@@ -11,6 +11,9 @@
11 <BindInputPaths Include="$(OutputPath)x86" BindName='x86' />
12 <BindInputPaths Include="$(OutputPath)x64" BindName='x64' />
13 <BindInputPaths Include="$(OutputPath)arm64" BindName='arm64' />
14 + <BindInputPaths Include="$(PkgMicrosoft_NET_Tools_NETCoreCheck_x86)\win-x86" BindName='x86' />
15 + <BindInputPaths Include="$(PkgMicrosoft_NET_Tools_NETCoreCheck_x64)\win-x64" BindName='x64' />
16 + <BindInputPaths Include="$(PkgMicrosoft_NET_Tools_NETCoreCheck_arm64)\win-arm64" BindName='arm64' />
17 </ItemGroup>
18
19 <ItemGroup>
@@ -33,5 +36,8 @@
36 <ItemGroup>
37 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
38 <PackageReference Include="GitInfo" PrivateAssets="All" />
39 + <PackageReference Include="Microsoft.NET.Tools.NETCoreCheck.x86" GeneratePathProperty="true" />
40 + <PackageReference Include="Microsoft.NET.Tools.NETCoreCheck.x64" GeneratePathProperty="true" />
41 + <PackageReference Include="Microsoft.NET.Tools.NETCoreCheck.arm64" GeneratePathProperty="true" />
42 </ItemGroup>
43 </Project>
src/internal/SetBuildNumber/Directory.Packages.props.pp
+6
@@ -93,4 +93,10 @@
93 <PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
94 <PackageVersion Include="xunit.assert" Version="2.4.2" />
95 </ItemGroup>
96 +
97 + <ItemGroup>
98 + <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.x86" Version="6.0.0" />
99 + <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.x64" Version="6.0.0" />
100 + <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.arm64" Version="6.0.0" />
101 + </ItemGroup>
102 </Project>