aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/wix/WixToolset.Extensibility/Data/IBindContext.cs15
-rw-r--r--src/test/burn/Directory.wixproj.props1
-rw-r--r--src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs2
-rw-r--r--src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs2
-rw-r--r--src/test/wix/TestData/WixprojPackageVcxprojWindowsAppMultiArch/Package.wxs2
-rw-r--r--src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs59
-rw-r--r--src/wix/WixToolset.BuildTasks/WixBuild.cs9
-rw-r--r--src/wix/WixToolset.Core.Native/FileSystem.cs4
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs31
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs131
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs5
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/MsiBackend.cs2
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/MsmBackend.cs2
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs2
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs (renamed from src/wix/WixToolset.Core.WindowsInstaller/Bind/ValidateDatabaseCommand.cs)47
-rw-r--r--src/wix/WixToolset.Core/BindContext.cs6
-rw-r--r--src/wix/WixToolset.Core/CommandLine/BuildCommand.cs27
-rw-r--r--src/wix/WixToolset.Sdk/tools/wix.targets39
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/ModuleFixture.cs93
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs65
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/BindVariables/PackageWithBindVariables.wxs2
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/.data/test.msmbin24576 -> 0 bytes
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/Package.wxs3
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/Validation/PackageWithIceIssues.wxs32
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/ValidationFixture.cs133
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/MsbuildFixture.cs81
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/MsbuildUtilities.cs3
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/MsiPackage.wixproj65
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.en-us.wxl11
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.wxs26
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/PackageComponents.wxs10
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/data/test.txt1
-rw-r--r--src/wix/test/WixToolsetTest.Sdk/TestData/SimpleMsiPackage/MsiPackage/Package.wxs2
33 files changed, 711 insertions, 202 deletions
diff --git a/src/api/wix/WixToolset.Extensibility/Data/IBindContext.cs b/src/api/wix/WixToolset.Extensibility/Data/IBindContext.cs
index d0c65683..671da292 100644
--- a/src/api/wix/WixToolset.Extensibility/Data/IBindContext.cs
+++ b/src/api/wix/WixToolset.Extensibility/Data/IBindContext.cs
@@ -53,11 +53,6 @@ namespace WixToolset.Extensibility.Data
53 IReadOnlyCollection<IFileSystemExtension> FileSystemExtensions { get; set; } 53 IReadOnlyCollection<IFileSystemExtension> FileSystemExtensions { get; set; }
54 54
55 /// <summary> 55 /// <summary>
56 /// Set of ICEs to execute.
57 /// </summary>
58 IReadOnlyCollection<string> Ices { get; set; }
59
60 /// <summary>
61 /// Intermedaite folder. 56 /// Intermedaite folder.
62 /// </summary> 57 /// </summary>
63 string IntermediateFolder { get; set; } 58 string IntermediateFolder { get; set; }
@@ -98,16 +93,6 @@ namespace WixToolset.Extensibility.Data
98 int? ResolvedLcid { get; set; } 93 int? ResolvedLcid { get; set; }
99 94
100 /// <summary> 95 /// <summary>
101 /// Set of ICEs to skip.
102 /// </summary>
103 IReadOnlyCollection<string> SuppressIces { get; set; }
104
105 /// <summary>
106 /// Skip all ICEs.
107 /// </summary>
108 bool SuppressValidation { get; set; }
109
110 /// <summary>
111 /// Skip creation of output. 96 /// Skip creation of output.
112 /// </summary> 97 /// </summary>
113 bool SuppressLayout { get; set; } 98 bool SuppressLayout { get; set; }
diff --git a/src/test/burn/Directory.wixproj.props b/src/test/burn/Directory.wixproj.props
index af5ef196..21ab5107 100644
--- a/src/test/burn/Directory.wixproj.props
+++ b/src/test/burn/Directory.wixproj.props
@@ -7,6 +7,7 @@
7 <DefaultCompressionLevel>None</DefaultCompressionLevel> 7 <DefaultCompressionLevel>None</DefaultCompressionLevel>
8 <CompilerAdditionalOptions>-wx</CompilerAdditionalOptions> 8 <CompilerAdditionalOptions>-wx</CompilerAdditionalOptions>
9 <SuppressSpecificWarnings>1154;$(SuppressSpecificWarnings)</SuppressSpecificWarnings> 9 <SuppressSpecificWarnings>1154;$(SuppressSpecificWarnings)</SuppressSpecificWarnings>
10 <SuppressValidation>true</SuppressValidation>
10 <ForTestingUseOnlyWixextPath>$(BaseOutputPath)$(Configuration)\netstandard2.0\ForTestingUseOnly.wixext.dll</ForTestingUseOnlyWixextPath> 11 <ForTestingUseOnlyWixextPath>$(BaseOutputPath)$(Configuration)\netstandard2.0\ForTestingUseOnly.wixext.dll</ForTestingUseOnlyWixextPath>
11 </PropertyGroup> 12 </PropertyGroup>
12</Project> 13</Project>
diff --git a/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs b/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs
index c228bb33..cbc8cae1 100644
--- a/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs
+++ b/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs
@@ -1,5 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name='~WebApp' Manufacturer='WiX Toolset' Version='0.0.1' UpgradeCode='00000000-0000-0000-0000-000000000000'> 2 <Package Name='~WebApp' Manufacturer='WiX Toolset' Version='0.0.1' UpgradeCode='41a2c17e-1976-465b-bcde-eae03516ca68'>
3 3
4 <StandardDirectory Id='ProgramFiles6432Folder'> 4 <StandardDirectory Id='ProgramFiles6432Folder'>
5 <Directory Id='ApplicationFolder' Name='~Web App'> 5 <Directory Id='ApplicationFolder' Name='~Web App'>
diff --git a/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs b/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs
index c0370683..fe849608 100644
--- a/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs
+++ b/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs
@@ -1,5 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name='!(loc.PackageName)' Manufacturer='WiX Toolset' Version='0.0.1' UpgradeCode='00000000-0000-0000-0000-000000000000'> 2 <Package Name='!(loc.PackageName)' Manufacturer='WiX Toolset' Version='0.0.1' UpgradeCode='41a2c17e-1976-465b-bcde-eae03516ca68'>
3 3
4 <StandardDirectory Id='ProgramFiles6432Folder'> 4 <StandardDirectory Id='ProgramFiles6432Folder'>
5 <Directory Id='ApplicationFolder' Name='Test App'> 5 <Directory Id='ApplicationFolder' Name='Test App'>
diff --git a/src/test/wix/TestData/WixprojPackageVcxprojWindowsAppMultiArch/Package.wxs b/src/test/wix/TestData/WixprojPackageVcxprojWindowsAppMultiArch/Package.wxs
index 9d3df756..ad95dac3 100644
--- a/src/test/wix/TestData/WixprojPackageVcxprojWindowsAppMultiArch/Package.wxs
+++ b/src/test/wix/TestData/WixprojPackageVcxprojWindowsAppMultiArch/Package.wxs
@@ -1,5 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name='WixprojPackageVcxprojWindowsApp' Manufacturer='WiX Toolset' Version='0.0.1' UpgradeCode='00000000-0000-0000-0000-000000000000'> 2 <Package Name='WixprojPackageVcxprojWindowsApp' Manufacturer='WiX Toolset' Version='0.0.1' UpgradeCode='41a2c17e-1976-465b-bcde-eae03516ca68'>
3 3
4 <StandardDirectory Id='ProgramFilesFolder'> 4 <StandardDirectory Id='ProgramFilesFolder'>
5 <Directory Id='Application32Folder' Name='Test App (32-bit)' /> 5 <Directory Id='Application32Folder' Name='Test App (32-bit)' />
diff --git a/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs b/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs
new file mode 100644
index 00000000..ae708c0e
--- /dev/null
+++ b/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs
@@ -0,0 +1,59 @@
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.BuildTasks
4{
5 using Microsoft.Build.Framework;
6
7 /// <summary>
8 /// An MSBuild task to run WiX to detach bundle engine to be signed.
9 /// </summary>
10 public sealed partial class WindowsInstallerValidation : WixExeBaseTask
11 {
12 /// <summary>
13 /// Gets or sets the path to the database to validate.
14 /// </summary>
15 [Required]
16 public ITaskItem DatabaseFile { get; set; }
17
18 /// <summary>
19 /// Gets or sets the intermedidate folder to use.
20 /// </summary>
21 public ITaskItem IntermediateDirectory { get; set; }
22
23 /// <summary>
24 /// Gets or sets the paths to ICE CUBes to execute.
25 /// </summary>
26 public string[] CubeFiles { get; set; }
27
28 /// <summary>
29 /// Gets or sets the ICEs to execute.
30 /// </summary>
31 public string[] Ices { get; set; }
32
33 /// <summary>
34 /// Gets or sets the ICEs to suppress.
35 /// </summary>
36 public string[] SuppressIces { get; set; }
37
38 /// <summary>
39 /// Gets or sets the .wixpdb for the database.
40 /// </summary>
41 public ITaskItem WixpdbFile { get; set; }
42
43 protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
44 {
45 commandLineBuilder.AppendTextUnquoted("msi validate");
46
47 commandLineBuilder.AppendFileNameIfNotNull(this.DatabaseFile);
48 commandLineBuilder.AppendSwitchIfNotNull("-pdb ", this.WixpdbFile);
49 commandLineBuilder.AppendSwitchIfNotNull("-intermediatefolder ", this.IntermediateDirectory);
50 commandLineBuilder.AppendArrayIfNotNull("-cub ", this.CubeFiles);
51 commandLineBuilder.AppendArrayIfNotNull("-ice ", this.Ices);
52 commandLineBuilder.AppendArrayIfNotNull("-sice ", this.SuppressIces);
53
54 base.BuildCommandLine(commandLineBuilder);
55
56 commandLineBuilder.AppendTextIfNotWhitespace(this.AdditionalOptions);
57 }
58 }
59}
diff --git a/src/wix/WixToolset.BuildTasks/WixBuild.cs b/src/wix/WixToolset.BuildTasks/WixBuild.cs
index 2d35c391..11de0242 100644
--- a/src/wix/WixToolset.BuildTasks/WixBuild.cs
+++ b/src/wix/WixToolset.BuildTasks/WixBuild.cs
@@ -64,13 +64,8 @@ namespace WixToolset.BuildTasks
64 public ITaskItem UnreferencedSymbolsFile { get; set; } 64 public ITaskItem UnreferencedSymbolsFile { get; set; }
65 65
66 public ITaskItem WixProjectFile { get; set; } 66 public ITaskItem WixProjectFile { get; set; }
67 public string[] WixVariables { get; set; }
68
69 public bool SuppressValidation { get; set; }
70 67
71 public string[] SuppressIces { get; set; } 68 public string[] WixVariables { get; set; }
72
73 public string AdditionalCub { get; set; }
74 69
75 protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder) 70 protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
76 { 71 {
@@ -85,8 +80,6 @@ namespace WixToolset.BuildTasks
85 commandLineBuilder.AppendArrayIfNotNull("-d ", this.DefineConstants); 80 commandLineBuilder.AppendArrayIfNotNull("-d ", this.DefineConstants);
86 commandLineBuilder.AppendArrayIfNotNull("-I ", this.IncludeSearchPaths); 81 commandLineBuilder.AppendArrayIfNotNull("-I ", this.IncludeSearchPaths);
87 commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.ReferencePaths); 82 commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.ReferencePaths);
88 commandLineBuilder.AppendIfTrue("-sval", this.SuppressValidation);
89 commandLineBuilder.AppendArrayIfNotNull("-sice ", this.SuppressIces);
90 commandLineBuilder.AppendSwitchIfNotNull("-usf ", this.UnreferencedSymbolsFile); 83 commandLineBuilder.AppendSwitchIfNotNull("-usf ", this.UnreferencedSymbolsFile);
91 commandLineBuilder.AppendSwitchIfNotNull("-cc ", this.CabinetCachePath); 84 commandLineBuilder.AppendSwitchIfNotNull("-cc ", this.CabinetCachePath);
92 commandLineBuilder.AppendSwitchIfNotNull("-intermediatefolder ", this.IntermediateDirectory); 85 commandLineBuilder.AppendSwitchIfNotNull("-intermediatefolder ", this.IntermediateDirectory);
diff --git a/src/wix/WixToolset.Core.Native/FileSystem.cs b/src/wix/WixToolset.Core.Native/FileSystem.cs
index d843a9e8..3dc336d6 100644
--- a/src/wix/WixToolset.Core.Native/FileSystem.cs
+++ b/src/wix/WixToolset.Core.Native/FileSystem.cs
@@ -62,14 +62,14 @@ namespace WixToolset.Core.Native
62 62
63 private static void EnsureDirectoryWithoutFile(string path) 63 private static void EnsureDirectoryWithoutFile(string path)
64 { 64 {
65 File.Delete(path);
66
67 var directory = Path.GetDirectoryName(path); 65 var directory = Path.GetDirectoryName(path);
68 66
69 if (!String.IsNullOrEmpty(directory)) 67 if (!String.IsNullOrEmpty(directory))
70 { 68 {
71 Directory.CreateDirectory(directory); 69 Directory.CreateDirectory(directory);
72 } 70 }
71
72 File.Delete(path);
73 } 73 }
74 74
75 [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 75 [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index f2a8b9c6..ab471702 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -21,11 +21,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
21 // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. 21 // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs.
22 internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); 22 internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}");
23 23
24 public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtension, string cubeFile) : this(context, backendExtension, null, cubeFile) 24 public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtension, IEnumerable<SubStorage> subStorages = null)
25 {
26 }
27
28 public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtension, IEnumerable<SubStorage> subStorages, string cubeFile)
29 { 25 {
30 this.ServiceProvider = context.ServiceProvider; 26 this.ServiceProvider = context.ServiceProvider;
31 27
@@ -53,11 +49,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
53 49
54 this.SubStorages = subStorages; 50 this.SubStorages = subStorages;
55 51
56 this.SuppressValidation = context.SuppressValidation;
57 this.Ices = context.Ices;
58 this.SuppressedIces = context.SuppressIces;
59 this.CubeFiles = String.IsNullOrEmpty(cubeFile) ? null : new[] { cubeFile };
60
61 this.BackendExtensions = backendExtension; 52 this.BackendExtensions = backendExtension;
62 } 53 }
63 54
@@ -109,12 +100,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
109 100
110 private bool SuppressValidation { get; } 101 private bool SuppressValidation { get; }
111 102
112 private IEnumerable<string> Ices { get; }
113
114 private IEnumerable<string> SuppressedIces { get; }
115
116 private IEnumerable<string> CubeFiles { get; }
117
118 public IBindResult Execute() 103 public IBindResult Execute()
119 { 104 {
120 if (!this.Intermediate.HasLevel(Data.IntermediateLevels.Linked) || !this.Intermediate.HasLevel(Data.IntermediateLevels.Resolved)) 105 if (!this.Intermediate.HasLevel(Data.IntermediateLevels.Linked) || !this.Intermediate.HasLevel(Data.IntermediateLevels.Resolved))
@@ -507,20 +492,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
507 return null; 492 return null;
508 } 493 }
509 494
510 // Validate the output if there are CUBe files and we're not explicitly suppressing validation.
511 if (this.CubeFiles != null && !this.SuppressValidation)
512 {
513 var command = new ValidateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.IntermediateFolder, data, this.OutputPath, this.CubeFiles, this.Ices, this.SuppressedIces);
514 command.Execute();
515
516 trackedFiles.AddRange(command.TrackedFiles);
517 }
518
519 if (this.Messaging.EncounteredError)
520 {
521 return null;
522 }
523
524 // Process uncompressed files. 495 // Process uncompressed files.
525 if (!this.SuppressLayout && uncompressedFiles.Any()) 496 if (!this.SuppressLayout && uncompressedFiles.Any())
526 { 497 {
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
new file mode 100644
index 00000000..7d77aa30
--- /dev/null
+++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
@@ -0,0 +1,131 @@
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.Core.WindowsInstaller.CommandLine
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using WixToolset.Core.WindowsInstaller.Validate;
11 using WixToolset.Data.WindowsInstaller;
12 using WixToolset.Extensibility.Services;
13
14 internal class ValidateSubcommand : WindowsInstallerSubcommandBase
15 {
16 public ValidateSubcommand(IServiceProvider serviceProvider)
17 {
18 this.Messaging = serviceProvider.GetService<IMessaging>();
19 }
20
21 private IMessaging Messaging { get; }
22
23 private string DatabasePath { get; set; }
24
25 private string WixpdbPath { get; set; }
26
27 private string IntermediateFolder { get; set; }
28
29 private List<string> CubeFiles { get; } = new List<string>();
30
31 private List<string> Ices { get; } = new List<string>();
32
33 private List<string> SuppressIces { get; } = new List<string>();
34
35 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
36 {
37 WindowsInstallerData data = null;
38
39 if (String.IsNullOrEmpty(this.DatabasePath))
40 {
41 Console.Error.WriteLine("Input MSI or MSM database is required");
42 return Task.FromResult(-1);
43 }
44
45 if (this.CubeFiles.Count == 0)
46 {
47 var ext = Path.GetExtension(this.DatabasePath);
48 switch (ext.ToLowerInvariant())
49 {
50 case ".msi":
51 this.CubeFiles.Add("darice.cub");
52 break;
53
54 case ".msm":
55 this.CubeFiles.Add("mergemod.cub");
56 break;
57
58 default:
59 Console.Error.WriteLine("Unknown extension: {0}. Use the -cub switch to specify the path to the ICE CUBe file", ext);
60 return Task.FromResult(-1);
61 }
62 }
63
64 if (String.IsNullOrEmpty(this.WixpdbPath))
65 {
66 this.WixpdbPath = Path.ChangeExtension(this.DatabasePath, ".wixpdb");
67 }
68
69 if (String.IsNullOrEmpty(this.IntermediateFolder))
70 {
71 this.IntermediateFolder = Path.GetTempPath();
72 }
73
74 if (File.Exists(this.WixpdbPath))
75 {
76 data = WindowsInstallerData.Load(this.WixpdbPath);
77 }
78
79 var command = new ValidateDatabaseCommand(this.Messaging, this.IntermediateFolder, this.DatabasePath, data, this.CubeFiles, this.Ices, this.SuppressIces);
80 command.Execute();
81
82 return Task.FromResult(this.Messaging.EncounteredError ? 1 : 0);
83 }
84
85 public override bool TryParseArgument(ICommandLineParser parser, string argument)
86 {
87 if (parser.IsSwitch(argument))
88 {
89 var parameter = argument.Substring(1);
90 switch (parameter.ToLowerInvariant())
91 {
92 case "cub":
93 {
94 var value = parser.GetNextArgumentOrError(argument);
95 this.CubeFiles.Add(value);
96 return true;
97 }
98
99 case "ice":
100 {
101 var value = parser.GetNextArgumentOrError(argument);
102 this.Ices.Add(value);
103 return true;
104 }
105
106 case "intermediatefolder":
107 this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(argument);
108 return true;
109
110 case "pdb":
111 this.WixpdbPath = parser.GetNextArgumentAsFilePathOrError(argument);
112 return true;
113
114 case "sice":
115 {
116 var value = parser.GetNextArgumentOrError(argument);
117 this.SuppressIces.Add(value);
118 return true;
119 }
120 }
121 }
122 else if (String.IsNullOrEmpty(this.DatabasePath))
123 {
124 this.DatabasePath = argument;
125 return true;
126 }
127
128 return false;
129 }
130 }
131}
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs
index db178ddf..a0da7fa4 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs
@@ -48,6 +48,10 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
48 case "inscribe": 48 case "inscribe":
49 this.Subcommand = new InscribeSubcommand(this.ServiceProvider); 49 this.Subcommand = new InscribeSubcommand(this.ServiceProvider);
50 return true; 50 return true;
51
52 case "validate":
53 this.Subcommand = new ValidateSubcommand(this.ServiceProvider);
54 return true;
51 } 55 }
52 56
53 return false; 57 return false;
@@ -68,6 +72,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
68 Console.WriteLine("Commands:"); 72 Console.WriteLine("Commands:");
69 Console.WriteLine(); 73 Console.WriteLine();
70 Console.WriteLine(" inscribe Updates MSI database with cabinet signature information."); 74 Console.WriteLine(" inscribe Updates MSI database with cabinet signature information.");
75 Console.WriteLine(" validate Validates MSI database using standard or custom ICEs.");
71 } 76 }
72 } 77 }
73} 78}
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/MsiBackend.cs b/src/wix/WixToolset.Core.WindowsInstaller/MsiBackend.cs
index 37de1904..33aa7a74 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/MsiBackend.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/MsiBackend.cs
@@ -27,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller
27 var dispose = true; 27 var dispose = true;
28 try 28 try
29 { 29 {
30 var command = new BindDatabaseCommand(context, backendExtensions, "darice.cub"); 30 var command = new BindDatabaseCommand(context, backendExtensions);
31 result = command.Execute(); 31 result = command.Execute();
32 32
33 foreach (var extension in backendExtensions) 33 foreach (var extension in backendExtensions)
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/MsmBackend.cs b/src/wix/WixToolset.Core.WindowsInstaller/MsmBackend.cs
index 450bf888..02ea5f45 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/MsmBackend.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/MsmBackend.cs
@@ -26,7 +26,7 @@ namespace WixToolset.Core.WindowsInstaller
26 IBindResult result = null; 26 IBindResult result = null;
27 try 27 try
28 { 28 {
29 var command = new BindDatabaseCommand(context, backendExtensions, "mergemod.cub"); 29 var command = new BindDatabaseCommand(context, backendExtensions);
30 result = command.Execute(); 30 result = command.Execute();
31 31
32 foreach (var extension in backendExtensions) 32 foreach (var extension in backendExtensions)
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs b/src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs
index 1ef9671b..d1f5eb99 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs
@@ -52,7 +52,7 @@ namespace WixToolset.Core.WindowsInstaller
52 IBindResult result = null; 52 IBindResult result = null;
53 try 53 try
54 { 54 {
55 var command = new BindDatabaseCommand(context, backendExtensions, subStorages, null); 55 var command = new BindDatabaseCommand(context, backendExtensions, subStorages);
56 result = command.Execute(); 56 result = command.Execute();
57 57
58 foreach (var extension in backendExtensions) 58 foreach (var extension in backendExtensions)
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/ValidateDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
index cf1e21c2..fe2fd2c2 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/ValidateDatabaseCommand.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
@@ -1,6 +1,6 @@
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. 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 2
3namespace WixToolset.Core.WindowsInstaller.Bind 3namespace WixToolset.Core.WindowsInstaller.Validate
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
@@ -18,18 +18,17 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18 // Set of ICEs that have equivalent-or-better checks in WiX. 18 // Set of ICEs that have equivalent-or-better checks in WiX.
19 private static readonly string[] WellKnownSuppressedIces = new[] { "ICE08", "ICE33", "ICE47", "ICE66" }; 19 private static readonly string[] WellKnownSuppressedIces = new[] { "ICE08", "ICE33", "ICE47", "ICE66" };
20 20
21 public ValidateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, string intermediateFolder, WindowsInstallerData data, string outputPath, IEnumerable<string> cubeFiles, IEnumerable<string> ices, IEnumerable<string> suppressedIces) 21 public ValidateDatabaseCommand(IMessaging messaging, string intermediateFolder, string databasePath, WindowsInstallerData data, IEnumerable<string> cubeFiles, IEnumerable<string> ices, IEnumerable<string> suppressedIces)
22 { 22 {
23 this.Messaging = messaging; 23 this.Messaging = messaging;
24 this.BackendHelper = backendHelper;
25 this.Data = data; 24 this.Data = data;
26 this.OutputPath = outputPath; 25 this.DatabasePath = databasePath;
27 this.CubeFiles = cubeFiles; 26 this.CubeFiles = cubeFiles;
28 this.Ices = ices; 27 this.Ices = ices;
29 this.SuppressedIces = suppressedIces == null ? WellKnownSuppressedIces : suppressedIces.Union(WellKnownSuppressedIces); 28 this.SuppressedIces = suppressedIces == null ? WellKnownSuppressedIces : suppressedIces.Union(WellKnownSuppressedIces);
30 29
31 this.IntermediateFolder = intermediateFolder; 30 this.IntermediateFolder = intermediateFolder;
32 this.OutputSourceLineNumber = new SourceLineNumber(outputPath); 31 this.OutputSourceLineNumber = new SourceLineNumber(databasePath);
33 } 32 }
34 33
35 public IEnumerable<ITrackedFile> TrackedFiles { get; private set; } 34 public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
@@ -41,11 +40,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
41 40
42 private IMessaging Messaging { get; } 41 private IMessaging Messaging { get; }
43 42
44 private IBackendHelper BackendHelper { get; }
45
46 private WindowsInstallerData Data { get; } 43 private WindowsInstallerData Data { get; }
47 44
48 private string OutputPath { get; } 45 private string DatabasePath { get; }
49 46
50 private IEnumerable<string> CubeFiles { get; } 47 private IEnumerable<string> CubeFiles { get; }
51 48
@@ -64,34 +61,34 @@ namespace WixToolset.Core.WindowsInstaller.Bind
64 61
65 public void Execute() 62 public void Execute()
66 { 63 {
67 var trackedFiles = new List<ITrackedFile>();
68 var stopwatch = Stopwatch.StartNew(); 64 var stopwatch = Stopwatch.StartNew();
69 65
70 this.Messaging.Write(VerboseMessages.ValidatingDatabase()); 66 this.Messaging.Write(VerboseMessages.ValidatingDatabase());
71 67
72 // Ensure the temporary files can be created the working folder.
73 var workingFolder = Path.Combine(this.IntermediateFolder, "_validate");
74 Directory.CreateDirectory(workingFolder);
75
76 // Copy the database to a temporary location so it can be manipulated. 68 // Copy the database to a temporary location so it can be manipulated.
77 // Ensure it is not read-only. 69 // Ensure it is not read-only.
78 var workingDatabasePath = Path.Combine(workingFolder, Path.GetFileName(this.OutputPath)); 70 var workingDatabaseFilename = String.Concat(Path.GetFileNameWithoutExtension(this.DatabasePath), "_validate", Path.GetExtension(this.DatabasePath));
79 FileSystem.CopyFile(this.OutputPath, workingDatabasePath, allowHardlink: false); 71 var workingDatabasePath = Path.Combine(this.IntermediateFolder, workingDatabaseFilename);
80 72 try
81 var trackWorkingDatabase = this.BackendHelper.TrackFile(workingDatabasePath, TrackedFileType.Temporary); 73 {
82 trackedFiles.Add(trackWorkingDatabase); 74 FileSystem.CopyFile(this.DatabasePath, workingDatabasePath, allowHardlink: false);
83 75
84 var attributes = File.GetAttributes(workingDatabasePath); 76 var attributes = File.GetAttributes(workingDatabasePath);
85 File.SetAttributes(workingDatabasePath, attributes & ~FileAttributes.ReadOnly); 77 File.SetAttributes(workingDatabasePath, attributes & ~FileAttributes.ReadOnly);
86 78
87 var validator = new WindowsInstallerValidator(this, workingDatabasePath, this.CubeFiles, this.Ices, this.SuppressedIces); 79 var validator = new WindowsInstallerValidator(this, workingDatabasePath, this.CubeFiles, this.Ices, this.SuppressedIces);
88 validator.Execute(); 80 validator.Execute();
81 }
82 finally
83 {
84 if (File.Exists(workingDatabasePath))
85 {
86 File.Delete(workingDatabasePath);
87 }
88 }
89 89
90 stopwatch.Stop(); 90 stopwatch.Stop();
91 this.Messaging.Write(VerboseMessages.ValidatedDatabase(stopwatch.ElapsedMilliseconds)); 91 this.Messaging.Write(VerboseMessages.ValidatedDatabase(stopwatch.ElapsedMilliseconds));
92
93
94 this.TrackedFiles = trackedFiles;
95 } 92 }
96 93
97 private void LogValidationMessage(ValidationMessage message) 94 private void LogValidationMessage(ValidationMessage message)
diff --git a/src/wix/WixToolset.Core/BindContext.cs b/src/wix/WixToolset.Core/BindContext.cs
index 052382f1..9dd6aa46 100644
--- a/src/wix/WixToolset.Core/BindContext.cs
+++ b/src/wix/WixToolset.Core/BindContext.cs
@@ -36,8 +36,6 @@ namespace WixToolset.Core
36 36
37 public IReadOnlyCollection<IFileSystemExtension> FileSystemExtensions { get; set; } 37 public IReadOnlyCollection<IFileSystemExtension> FileSystemExtensions { get; set; }
38 38
39 public IReadOnlyCollection<string> Ices { get; set; }
40
41 public string IntermediateFolder { get; set; } 39 public string IntermediateFolder { get; set; }
42 40
43 public Intermediate IntermediateRepresentation { get; set; } 41 public Intermediate IntermediateRepresentation { get; set; }
@@ -54,10 +52,6 @@ namespace WixToolset.Core
54 52
55 public int? ResolvedLcid { get; set; } 53 public int? ResolvedLcid { get; set; }
56 54
57 public IReadOnlyCollection<string> SuppressIces { get; set; }
58
59 public bool SuppressValidation { get; set; }
60
61 public bool SuppressLayout { get; set; } 55 public bool SuppressLayout { get; set; }
62 56
63 public CancellationToken CancellationToken { get; set; } 57 public CancellationToken CancellationToken { get; set; }
diff --git a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
index 3ea47279..d289b557 100644
--- a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
+++ b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
@@ -349,14 +349,11 @@ namespace WixToolset.Core.CommandLine
349 context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles; 349 context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles;
350 context.Extensions = this.ExtensionManager.GetServices<IBinderExtension>(); 350 context.Extensions = this.ExtensionManager.GetServices<IBinderExtension>();
351 context.FileSystemExtensions = this.ExtensionManager.GetServices<IFileSystemExtension>(); 351 context.FileSystemExtensions = this.ExtensionManager.GetServices<IFileSystemExtension>();
352 context.Ices = this.commandLine.Ices;
353 context.IntermediateFolder = intermediateFolder; 352 context.IntermediateFolder = intermediateFolder;
354 context.IntermediateRepresentation = resolveResult.IntermediateRepresentation; 353 context.IntermediateRepresentation = resolveResult.IntermediateRepresentation;
355 context.OutputPath = this.OutputFile; 354 context.OutputPath = this.OutputFile;
356 context.PdbType = this.PdbType; 355 context.PdbType = this.PdbType;
357 context.PdbPath = this.PdbType == PdbType.None ? null : this.PdbFile ?? Path.ChangeExtension(this.OutputFile, ".wixpdb"); 356 context.PdbPath = this.PdbType == PdbType.None ? null : this.PdbFile ?? Path.ChangeExtension(this.OutputFile, ".wixpdb");
358 context.SuppressIces = this.commandLine.SuppressIces;
359 context.SuppressValidation = this.commandLine.SuppressValidation;
360 context.CancellationToken = cancellationToken; 357 context.CancellationToken = cancellationToken;
361 358
362 var binder = this.ServiceProvider.GetService<IBinder>(); 359 var binder = this.ServiceProvider.GetService<IBinder>();
@@ -540,12 +537,6 @@ namespace WixToolset.Core.CommandLine
540 537
541 public string TrackingFile { get; private set; } 538 public string TrackingFile { get; private set; }
542 539
543 public List<string> Ices { get; } = new List<string>();
544
545 public List<string> SuppressIces { get; } = new List<string>();
546
547 public bool SuppressValidation { get; set; }
548
549 public bool ResetAcls { get; set; } 540 public bool ResetAcls { get; set; }
550 541
551 public CommandLine(IServiceProvider serviceProvider, IMessaging messaging) 542 public CommandLine(IServiceProvider serviceProvider, IMessaging messaging)
@@ -627,13 +618,6 @@ namespace WixToolset.Core.CommandLine
627 parser.GetNextArgumentOrError(arg, this.IncludeSearchPaths); 618 parser.GetNextArgumentOrError(arg, this.IncludeSearchPaths);
628 return true; 619 return true;
629 620
630 case "ice":
631 {
632 var value = parser.GetNextArgumentOrError(arg);
633 this.Ices.Add(value);
634 return true;
635 }
636
637 case "intermediatefolder": 621 case "intermediatefolder":
638 this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(arg); 622 this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(arg);
639 return true; 623 return true;
@@ -670,17 +654,6 @@ namespace WixToolset.Core.CommandLine
670 return false; 654 return false;
671 } 655 }
672 656
673 case "sice":
674 {
675 var value = parser.GetNextArgumentOrError(arg);
676 this.SuppressIces.Add(value);
677 return true;
678 }
679
680 case "sval":
681 this.SuppressValidation = true;
682 return true;
683
684 case "resetacls": 657 case "resetacls":
685 this.ResetAcls = true; 658 this.ResetAcls = true;
686 return true; 659 return true;
diff --git a/src/wix/WixToolset.Sdk/tools/wix.targets b/src/wix/WixToolset.Sdk/tools/wix.targets
index 487c5cb3..bbb73a52 100644
--- a/src/wix/WixToolset.Sdk/tools/wix.targets
+++ b/src/wix/WixToolset.Sdk/tools/wix.targets
@@ -168,6 +168,10 @@
168 <UsingTask TaskName="ResolveWixReferences" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath)" Architecture="x86" /> 168 <UsingTask TaskName="ResolveWixReferences" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath)" Architecture="x86" />
169 <UsingTask TaskName="ResolveWixReferences" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath64)" Architecture="x64" /> 169 <UsingTask TaskName="ResolveWixReferences" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath64)" Architecture="x64" />
170 170
171 <UsingTask TaskName="WindowsInstallerValidation" Condition=" '$(WixTasksPath64)' == '' " AssemblyFile="$(WixTasksPath)" />
172 <UsingTask TaskName="WindowsInstallerValidation" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath)" Architecture="x86" />
173 <UsingTask TaskName="WindowsInstallerValidation" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath64)" Architecture="x64" />
174
171 <!-- 175 <!--
172 *********************************************************************************************** 176 ***********************************************************************************************
173 *********************************************************************************************** 177 ***********************************************************************************************
@@ -553,6 +557,10 @@
553 ================================================================================================ 557 ================================================================================================
554 --> 558 -->
555 <PropertyGroup> 559 <PropertyGroup>
560 <CompileDependsOn>
561 $(CompileDependsOn);
562 WindowsInstallerValidation
563 </CompileDependsOn>
556 <CoreCompileDependsOn> 564 <CoreCompileDependsOn>
557 AssignTargetPaths; 565 AssignTargetPaths;
558 CreateManifestResourceNames; 566 CreateManifestResourceNames;
@@ -604,9 +612,6 @@
604 Pedantic="$(Pedantic)" 612 Pedantic="$(Pedantic)"
605 ReferencePaths="$(ReferencePaths)" 613 ReferencePaths="$(ReferencePaths)"
606 614
607 SuppressSpecificWarnings="$(SuppressSpecificWarnings)"
608 TreatSpecificWarningsAsErrors="$(TreatSpecificWarningsAsErrors)"
609
610 BindInputPaths="@(LinkerBindInputPaths)" 615 BindInputPaths="@(LinkerBindInputPaths)"
611 BindFiles="$(BindFiles)" 616 BindFiles="$(BindFiles)"
612 BindTrackingFile="$(IntermediateOutputPath)$(BindTrackingFilePrefix)%(CultureGroup.Identity)$(BindTrackingFileExtension)" 617 BindTrackingFile="$(IntermediateOutputPath)$(BindTrackingFilePrefix)%(CultureGroup.Identity)$(BindTrackingFileExtension)"
@@ -619,12 +624,10 @@
619 WixProjectFile="$(ProjectPath)" 624 WixProjectFile="$(ProjectPath)"
620 WixVariables="$(WixVariables)" 625 WixVariables="$(WixVariables)"
621 626
622 SuppressValidation="$(SuppressValidation)"
623 SuppressIces="$(SuppressIces)"
624 AdditionalCub="$(AdditionalCub)"
625
626 SuppressAllWarnings="$(SuppressAllWarnings)" 627 SuppressAllWarnings="$(SuppressAllWarnings)"
628 SuppressSpecificWarnings="$(SuppressSpecificWarnings)"
627 TreatWarningsAsErrors="$(TreatWarningsAsErrors)" 629 TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
630 TreatSpecificWarningsAsErrors="$(TreatSpecificWarningsAsErrors)"
628 VerboseOutput="$(VerboseOutput)" 631 VerboseOutput="$(VerboseOutput)"
629 632
630 RunAsSeparateProcess="$(RunWixToolsOutOfProc)" 633 RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
@@ -636,6 +639,28 @@
636 </ItemGroup> 639 </ItemGroup>
637 </Target> 640 </Target>
638 641
642 <Target
643 Name="WindowsInstallerValidation"
644 DependsOnTargets="CoreCompile"
645 Condition=" ('$(OutputType)' == 'Package' or '$(OutputType)' == 'Module') and '$(SuppressValidation)'!='true' ">
646 <WindowsInstallerValidation
647 DatabaseFile="$(IntermediateOutputPath)%(CultureGroup.OutputFolder)$(TargetFileName)"
648 WixpdbFile="$(IntermediateOutputPath)%(CultureGroup.OutputFolder)$(TargetPdbFileName)"
649 IntermediateDirectory="$(IntermediateOutputPath)%(CultureGroup.OutputFolder)"
650 Ices="$(Ices)"
651 SuppressIces="$(SuppressIces)"
652 CubeFiles="$(AdditionalCub)"
653
654 AdditionalOptions="$(ValidationAdditionalOptions)"
655
656 NoLogo="true"
657 SuppressAllWarnings="$(SuppressAllWarnings)"
658 SuppressSpecificWarnings="$(SuppressSpecificWarnings)"
659 TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
660 TreatSpecificWarningsAsErrors="$(TreatSpecificWarningsAsErrors)"
661 VerboseOutput="$(VerboseOutput)" />
662 </Target>
663
639 <!-- 664 <!--
640 ================================================================================================ 665 ================================================================================================
641 _CreateProjectDefineConstants 666 _CreateProjectDefineConstants
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/ModuleFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/ModuleFixture.cs
index 1c5e68f0..41418711 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/ModuleFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/ModuleFixture.cs
@@ -15,7 +15,7 @@ namespace WixToolsetTest.CoreIntegration
15 public class ModuleFixture 15 public class ModuleFixture
16 { 16 {
17 [Fact] 17 [Fact]
18 public void CanBuildSimpleModule() 18 public void CanBuildAndValidateSimpleModule()
19 { 19 {
20 var folder = TestData.Get(@"TestData\SimpleModule"); 20 var folder = TestData.Get(@"TestData\SimpleModule");
21 21
@@ -73,6 +73,30 @@ namespace WixToolsetTest.CoreIntegration
73 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE", 73 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
74 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE", 74 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
75 }, files.Select(f => Path.Combine(f.Path, f.Name)).ToArray()); 75 }, files.Select(f => Path.Combine(f.Path, f.Name)).ToArray());
76
77 var rows = Query.QueryDatabase(msmPath, new[] { "_SummaryInformation" });
78 WixAssert.CompareLineByLine(new[]
79 {
80 "_SummaryInformation:Title\tMerge Module",
81 "_SummaryInformation:Subject\tMergeModule1",
82 "_SummaryInformation:Author\tExample Company",
83 "_SummaryInformation:Keywords\tMergeModule, MSI, database",
84 "_SummaryInformation:Comments\tThis merge module contains the logic and data required to install MergeModule1.",
85 "_SummaryInformation:Template\tIntel;1033",
86 "_SummaryInformation:CodePage\t1252",
87 "_SummaryInformation:PageCount\t200",
88 "_SummaryInformation:WordCount\t0",
89 "_SummaryInformation:CharacterCount\t0",
90 "_SummaryInformation:Security\t2",
91 }, rows);
92
93 var validationResult = WixRunner.Execute(new[]
94 {
95 "msi", "validate",
96 "-intermediateFolder", intermediateFolder,
97 msmPath
98 });
99 validationResult.AssertSuccess();
76 } 100 }
77 } 101 }
78 102
@@ -109,5 +133,72 @@ namespace WixToolsetTest.CoreIntegration
109 }, rows); 133 }, rows);
110 } 134 }
111 } 135 }
136
137 [Fact]
138 public void CanMergeModule()
139 {
140 var msmFolder = TestData.Get(@"TestData\SimpleModule");
141 var folder = TestData.Get(@"TestData\SimpleMerge");
142
143 using (var fs = new DisposableFileSystem())
144 {
145 var intermediateFolder = fs.GetFolder();
146 var msiPath = Path.Combine(intermediateFolder, @"bin\test.msi");
147 var cabPath = Path.Combine(intermediateFolder, @"bin\cab1.cab");
148
149 var msmResult = WixRunner.Execute(new[]
150 {
151 "build",
152 Path.Combine(msmFolder, "Module.wxs"),
153 "-loc", Path.Combine(msmFolder, "Module.en-us.wxl"),
154 "-bindpath", Path.Combine(msmFolder, "data"),
155 "-intermediateFolder", intermediateFolder,
156 "-o", Path.Combine(intermediateFolder, "bin", "test", "test.msm")
157 });
158
159 msmResult.AssertSuccess();
160
161 var result = WixRunner.Execute(new[]
162 {
163 "build",
164 Path.Combine(folder, "Package.wxs"),
165 "-loc", Path.Combine(folder, "Package.en-us.wxl"),
166 "-bindpath", Path.Combine(intermediateFolder, "bin", "test"),
167 "-intermediateFolder", intermediateFolder,
168 "-o", msiPath
169 });
170
171 result.AssertSuccess();
172
173 var validationResult = WixRunner.Execute(new[]
174 {
175 "msi", "validate",
176 "-intermediateFolder", intermediateFolder,
177 msiPath
178 });
179 validationResult.AssertSuccess();
180
181 var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
182 var section = intermediate.Sections.Single();
183 Assert.Empty(section.Symbols.OfType<FileSymbol>());
184
185 var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
186 Assert.Empty(data.Tables["File"].Rows);
187
188 var results = Query.QueryDatabase(msiPath, new[] { "File" });
189 WixAssert.CompareLineByLine(new[]
190 {
191 "File:File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile1.txt\t17\t\t\t512\t1",
192 "File:File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile2.txt\t17\t\t\t512\t2",
193 }, results);
194
195 var files = Query.GetCabinetFiles(cabPath);
196 WixAssert.CompareLineByLine(new[]
197 {
198 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
199 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE"
200 }, files.Select(f => f.Name).ToArray());
201 }
202 }
112 } 203 }
113} 204}
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
index 2b3bfc88..f361a274 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
@@ -8,9 +8,6 @@ namespace WixToolsetTest.CoreIntegration
8 using Example.Extension; 8 using Example.Extension;
9 using WixBuildTools.TestSupport; 9 using WixBuildTools.TestSupport;
10 using WixToolset.Core.TestPackage; 10 using WixToolset.Core.TestPackage;
11 using WixToolset.Data;
12 using WixToolset.Data.Symbols;
13 using WixToolset.Data.WindowsInstaller;
14 using Xunit; 11 using Xunit;
15 12
16 public class MsiQueryFixture 13 public class MsiQueryFixture
@@ -835,68 +832,6 @@ namespace WixToolsetTest.CoreIntegration
835 } 832 }
836 833
837 [Fact] 834 [Fact]
838 public void CanMergeModule()
839 {
840 var msmFolder = TestData.Get(@"TestData\SimpleModule");
841 var folder = TestData.Get(@"TestData\SimpleMerge");
842
843 using (var fs = new DisposableFileSystem())
844 {
845 var intermediateFolder = fs.GetFolder();
846 var msiPath = Path.Combine(intermediateFolder, @"bin\test.msi");
847 var cabPath = Path.Combine(intermediateFolder, @"bin\cab1.cab");
848
849 var msmResult = WixRunner.Execute(new[]
850 {
851 "build",
852 Path.Combine(msmFolder, "Module.wxs"),
853 "-loc", Path.Combine(msmFolder, "Module.en-us.wxl"),
854 "-bindpath", Path.Combine(msmFolder, "data"),
855 "-intermediateFolder", intermediateFolder,
856 "-o", Path.Combine(intermediateFolder, "bin", "test", "test.msm")
857 });
858
859 msmResult.AssertSuccess();
860
861 var result = WixRunner.Execute(new[]
862 {
863 "build",
864 Path.Combine(folder, "Package.wxs"),
865 "-loc", Path.Combine(folder, "Package.en-us.wxl"),
866 "-bindpath", Path.Combine(intermediateFolder, "bin", "test"),
867 "-intermediateFolder", intermediateFolder,
868 "-o", msiPath
869 });
870
871 result.AssertSuccess();
872
873 Assert.True(File.Exists(msiPath));
874 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
875
876 var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
877 var section = intermediate.Sections.Single();
878 Assert.Empty(section.Symbols.OfType<FileSymbol>());
879
880 var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
881 Assert.Empty(data.Tables["File"].Rows);
882
883 var results = Query.QueryDatabase(msiPath, new[] { "File" });
884 WixAssert.CompareLineByLine(new[]
885 {
886 "File:File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile1.txt\t17\t\t\t512\t1",
887 "File:File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile2.txt\t17\t\t\t512\t2",
888 }, results);
889
890 var files = Query.GetCabinetFiles(cabPath);
891 WixAssert.CompareLineByLine(new[]
892 {
893 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
894 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE"
895 }, files.Select(f => f.Name).ToArray());
896 }
897 }
898
899 [Fact]
900 public void CanPublishComponentWithMultipleFeatureComponents() 835 public void CanPublishComponentWithMultipleFeatureComponents()
901 { 836 {
902 var folder = TestData.Get(@"TestData\PublishComponent"); 837 var folder = TestData.Get(@"TestData\PublishComponent");
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BindVariables/PackageWithBindVariables.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BindVariables/PackageWithBindVariables.wxs
index 377f7e11..2a0c374f 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BindVariables/PackageWithBindVariables.wxs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BindVariables/PackageWithBindVariables.wxs
@@ -1,5 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="PacakgeWithBindVariables" Version="!(bind.fileversion.TestBinaryFile)" Manufacturer="Example Corporation" UpgradeCode="00000000-0000-0000-0000-000000000000"> 2 <Package Name="PacakgeWithBindVariables" Version="!(bind.fileversion.TestBinaryFile)" Manufacturer="Example Corporation" UpgradeCode="41a2c17e-1976-465b-bcde-eae03516ca68">
3 3
4 <Property Id="TestPackageManufacturer" Value="!(bind.Property.Manufacturer)" /> 4 <Property Id="TestPackageManufacturer" Value="!(bind.Property.Manufacturer)" />
5 <Property Id="TestPackageName" Value="!(bind.Property.ProductName)" /> 5 <Property Id="TestPackageName" Value="!(bind.Property.ProductName)" />
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/.data/test.msm b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/.data/test.msm
deleted file mode 100644
index 6f179aba..00000000
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/.data/test.msm
+++ /dev/null
Binary files differ
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/Package.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/Package.wxs
index 3c999812..41dd19fc 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/Package.wxs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleMerge/Package.wxs
@@ -1,7 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="MsiPackage" Codepage="1252" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="yes" InstallerVersion="200" Scope="perMachine"> 2 <Package Name="MsiPackage" Codepage="1252" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="yes" InstallerVersion="200" Scope="perMachine">
3
4
5 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" /> 3 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
6 4
7 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)"> 5 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
@@ -12,7 +10,6 @@
12 <Fragment> 10 <Fragment>
13 <StandardDirectory Id="ProgramFilesFolder"> 11 <StandardDirectory Id="ProgramFilesFolder">
14 <Directory Id="INSTALLFOLDER" Name="MsiPackage"> 12 <Directory Id="INSTALLFOLDER" Name="MsiPackage">
15 <!-- -->
16 <Merge Id="TestMsm" Language="1033" SourceFile="test.msm" /> 13 <Merge Id="TestMsm" Language="1033" SourceFile="test.msm" />
17 </Directory> 14 </Directory>
18 </StandardDirectory> 15 </StandardDirectory>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Validation/PackageWithIceIssues.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Validation/PackageWithIceIssues.wxs
new file mode 100644
index 00000000..4d3acdf7
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Validation/PackageWithIceIssues.wxs
@@ -0,0 +1,32 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="ValidationPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 <MajorUpgrade DowngradeErrorMessage="Downgrade message" />
4
5 <Property Id="MyProperty" Value="1" />
6 <Launch Condition="Myproperty" Message="Invalid cased Property Id below causes ICE46" />
7
8 <CustomAction Id="CausesICE12Error" Directory="INSTALLFOLDER" Value="Test" />
9
10 <Feature Id="ProductFeature" Title="Product Feature">
11 <ComponentGroupRef Id="ProductComponents" />
12 </Feature>
13
14 <InstallExecuteSequence>
15 <Custom Action="CausesICE12Error" Before="AppSearch" />
16 </InstallExecuteSequence>
17 </Package>
18
19 <Fragment>
20 <StandardDirectory Id="ProgramFiles6432Folder">
21 <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
22 </StandardDirectory>
23 </Fragment>
24
25 <Fragment>
26 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
27 <Component>
28 <File Source="test.txt" />
29 </Component>
30 </ComponentGroup>
31 </Fragment>
32</Wix>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/ValidationFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/ValidationFixture.cs
new file mode 100644
index 00000000..48339b89
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/ValidationFixture.cs
@@ -0,0 +1,133 @@
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 WixToolsetTest.CoreIntegration
4{
5 using System.IO;
6 using System.Linq;
7 using WixBuildTools.TestSupport;
8 using WixToolset.Core.TestPackage;
9 using Xunit;
10
11 public class ValidationFixture
12 {
13 [Fact]
14 public void CanValidateMsiWithIceIssues()
15 {
16 var folder = TestData.Get(@"TestData");
17
18 using (var fs = new DisposableFileSystem())
19 {
20 var baseFolder = fs.GetFolder();
21 var intermediateFolder = Path.Combine(baseFolder, "obj");
22 var msiPath = Path.Combine(baseFolder, @"bin", "test.msi");
23
24 var result = WixRunner.Execute(new[]
25 {
26 "build",
27 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
28 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
29 "-intermediateFolder", intermediateFolder,
30 "-o", msiPath,
31 });
32
33 result.AssertSuccess();
34
35 var validationResult = WixRunner.Execute(new[]
36 {
37 "msi", "validate",
38 "-intermediateFolder", intermediateFolder,
39 msiPath
40 });
41
42 Assert.Equal(1, validationResult.ExitCode);
43
44 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
45 WixAssert.CompareLineByLine(new[]
46 {
47 @"ICE12: CustomAction: CausesICE12Error is of type: 35. Therefore it must come after CostFinalize @ 1000 in Seq Table: InstallExecuteSequence. CA Seq#: 49",
48 @"ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only."
49 }, messages);
50 }
51 }
52
53 [Fact]
54 public void CanValidateMsiSuppressIceError()
55 {
56 var folder = TestData.Get(@"TestData");
57
58 using (var fs = new DisposableFileSystem())
59 {
60 var baseFolder = fs.GetFolder();
61 var intermediateFolder = Path.Combine(baseFolder, "obj");
62 var msiPath = Path.Combine(baseFolder, @"bin", "test.msi");
63
64 var result = WixRunner.Execute(new[]
65 {
66 "build",
67 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
68 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
69 "-intermediateFolder", intermediateFolder,
70 "-o", msiPath,
71 });
72
73 result.AssertSuccess();
74
75 var validationResult = WixRunner.Execute(warningsAsErrors: false, new[]
76 {
77 "msi", "validate",
78 "-intermediateFolder", intermediateFolder,
79 "-sice", "ICE12",
80 msiPath
81 });
82
83 validationResult.AssertSuccess();
84
85 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
86 WixAssert.CompareLineByLine(new[]
87 {
88 @"ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only."
89 }, messages);
90 }
91 }
92
93 [Fact]
94 public void CanValidateMsiWithWarningsAsErrors()
95 {
96 var folder = TestData.Get(@"TestData");
97
98 using (var fs = new DisposableFileSystem())
99 {
100 var baseFolder = fs.GetFolder();
101 var intermediateFolder = Path.Combine(baseFolder, "obj");
102 var msiPath = Path.Combine(baseFolder, @"bin", "test.msi");
103
104 var result = WixRunner.Execute(new[]
105 {
106 "build",
107 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
108 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
109 "-intermediateFolder", intermediateFolder,
110 "-o", msiPath,
111 });
112
113 result.AssertSuccess();
114
115 var validationResult = WixRunner.Execute(warningsAsErrors: true, new[]
116 {
117 "msi", "validate",
118 "-intermediateFolder", intermediateFolder,
119 "-sice", "ICE12",
120 msiPath
121 });
122
123 Assert.Equal(1, validationResult.ExitCode);
124
125 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
126 WixAssert.CompareLineByLine(new[]
127 {
128 @"ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only."
129 }, messages);
130 }
131 }
132 }
133}
diff --git a/src/wix/test/WixToolsetTest.Sdk/MsbuildFixture.cs b/src/wix/test/WixToolsetTest.Sdk/MsbuildFixture.cs
index 3a9ce776..1a82c035 100644
--- a/src/wix/test/WixToolsetTest.Sdk/MsbuildFixture.cs
+++ b/src/wix/test/WixToolsetTest.Sdk/MsbuildFixture.cs
@@ -271,6 +271,7 @@ namespace WixToolsetTest.Sdk
271 var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[] 271 var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[]
272 { 272 {
273 wixpdbType == null ? String.Empty : $"-p:WixPdbType={wixpdbType}", 273 wixpdbType == null ? String.Empty : $"-p:WixPdbType={wixpdbType}",
274 "-p:SuppressValidation=true"
274 }); 275 });
275 result.AssertSuccess(); 276 result.AssertSuccess();
276 277
@@ -323,9 +324,44 @@ namespace WixToolsetTest.Sdk
323 [InlineData(BuildSystem.DotNetCoreSdk)] 324 [InlineData(BuildSystem.DotNetCoreSdk)]
324 [InlineData(BuildSystem.MSBuild)] 325 [InlineData(BuildSystem.MSBuild)]
325 [InlineData(BuildSystem.MSBuild64)] 326 [InlineData(BuildSystem.MSBuild64)]
326 public void CanBuildSimpleMsiPackageWithIceSuppressions(BuildSystem buildSystem) 327 public void CannotBuildMsiPackageWithIceIssues(BuildSystem buildSystem)
327 { 328 {
328 var sourceFolder = TestData.Get(@"TestData\SimpleMsiPackage\MsiPackage"); 329 var sourceFolder = TestData.Get(@"TestData\MsiPackageWithIceError\MsiPackage");
330
331 using (var fs = new TestDataFolderFileSystem())
332 {
333 fs.Initialize(sourceFolder);
334 var baseFolder = fs.BaseFolder;
335 var binFolder = Path.Combine(baseFolder, @"bin\");
336 var projectPath = Path.Combine(baseFolder, "MsiPackage.wixproj");
337
338 var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, suppressValidation: false);
339 Assert.Equal(1, result.ExitCode);
340
341 var iceIssues = result.Output.Where(line => line.Contains(": error") || line.Contains(": warning"))
342 .Select(line => line.Replace(baseFolder, "<baseFolder>")
343 .Replace("1>", String.Empty) // remove any multi-proc markers
344 .Replace("WIX204", "WIX0204") // normalize error number reporting because MSBuild is not consistent on zero padding
345 .Trim())
346 .OrderBy(s => s, StringComparer.OrdinalIgnoreCase)
347 .ToArray();
348 WixAssert.CompareLineByLine(new[]
349 {
350 @"<baseFolder>\Package.wxs(17): error WIX0204: ICE12: CustomAction: CausesICE12Error is of type: 35. Therefore it must come after CostFinalize @ 1000 in Seq Table: InstallExecuteSequence. CA Seq#: 49 [<baseFolder>\MsiPackage.wixproj]",
351 @"<baseFolder>\Package.wxs(17): error WIX0204: ICE12: CustomAction: CausesICE12Error is of type: 35. Therefore it must come after CostFinalize @ 1000 in Seq Table: InstallExecuteSequence. CA Seq#: 49 [<baseFolder>\MsiPackage.wixproj]",
352 @"<baseFolder>\Package.wxs(8): warning WIX1076: ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only. [<baseFolder>\MsiPackage.wixproj]",
353 @"<baseFolder>\Package.wxs(8): warning WIX1076: ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only. [<baseFolder>\MsiPackage.wixproj]",
354 }, iceIssues);
355 }
356 }
357
358 [Theory]
359 [InlineData(BuildSystem.DotNetCoreSdk)]
360 [InlineData(BuildSystem.MSBuild)]
361 [InlineData(BuildSystem.MSBuild64)]
362 public void CannotBuildMsiPackageWithIceWarningsAsErrors(BuildSystem buildSystem)
363 {
364 var sourceFolder = TestData.Get(@"TestData\MsiPackageWithIceError\MsiPackage");
329 365
330 using (var fs = new TestDataFolderFileSystem()) 366 using (var fs = new TestDataFolderFileSystem())
331 { 367 {
@@ -336,8 +372,45 @@ namespace WixToolsetTest.Sdk
336 372
337 var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[] 373 var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[]
338 { 374 {
339 MsbuildUtilities.GetQuotedPropertySwitch(buildSystem, "SuppressIces", "ICE45;ICE46"), 375 $"-p:TreatWarningsAsErrors=true",
340 }); 376 MsbuildUtilities.GetQuotedPropertySwitch(buildSystem, "SuppressIces", "ICE12"),
377 }, suppressValidation: false);
378 Assert.Equal(1, result.ExitCode);
379
380 var iceIssues = result.Output.Where(line => (line.Contains(": error") || line.Contains(": warning")))
381 .Select(line => line.Replace(baseFolder, "<baseFolder>")
382 .Replace("1>", String.Empty) // remove any multi-proc markers
383 .Replace("WIX204", "WIX0204") // normalize error number reporting because MSBuild is not consistent on zero padding
384 .Trim())
385 .OrderBy(s => s, StringComparer.OrdinalIgnoreCase)
386 .ToArray();
387 WixAssert.CompareLineByLine(new[]
388 {
389 @"<baseFolder>\Package.wxs(8): error WIX1076: ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only. [<baseFolder>\MsiPackage.wixproj]",
390 @"<baseFolder>\Package.wxs(8): error WIX1076: ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only. [<baseFolder>\MsiPackage.wixproj]",
391 }, iceIssues);
392 }
393 }
394
395 [Theory]
396 [InlineData(BuildSystem.DotNetCoreSdk)]
397 [InlineData(BuildSystem.MSBuild)]
398 [InlineData(BuildSystem.MSBuild64)]
399 public void CanBuildMsiPackageWithIceSuppressions(BuildSystem buildSystem)
400 {
401 var sourceFolder = TestData.Get(@"TestData\MsiPackageWithIceError\MsiPackage");
402
403 using (var fs = new TestDataFolderFileSystem())
404 {
405 fs.Initialize(sourceFolder);
406 var baseFolder = fs.BaseFolder;
407 var binFolder = Path.Combine(baseFolder, @"bin\");
408 var projectPath = Path.Combine(baseFolder, "MsiPackage.wixproj");
409
410 var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[]
411 {
412 MsbuildUtilities.GetQuotedPropertySwitch(buildSystem, "SuppressIces", "ICE12"),
413 }, suppressValidation: false);
341 result.AssertSuccess(); 414 result.AssertSuccess();
342 } 415 }
343 } 416 }
diff --git a/src/wix/test/WixToolsetTest.Sdk/MsbuildUtilities.cs b/src/wix/test/WixToolsetTest.Sdk/MsbuildUtilities.cs
index 28e0c219..875e3279 100644
--- a/src/wix/test/WixToolsetTest.Sdk/MsbuildUtilities.cs
+++ b/src/wix/test/WixToolsetTest.Sdk/MsbuildUtilities.cs
@@ -20,12 +20,13 @@ namespace WixToolsetTest.Sdk
20 public static readonly string WixMsbuildPath = Path.Combine(Path.GetDirectoryName(new Uri(typeof(MsbuildUtilities).Assembly.CodeBase).AbsolutePath), "..", "publish", "WixToolset.Sdk"); 20 public static readonly string WixMsbuildPath = Path.Combine(Path.GetDirectoryName(new Uri(typeof(MsbuildUtilities).Assembly.CodeBase).AbsolutePath), "..", "publish", "WixToolset.Sdk");
21 public static readonly string WixPropsPath = Path.Combine(WixMsbuildPath, "build", "WixToolset.Sdk.props"); 21 public static readonly string WixPropsPath = Path.Combine(WixMsbuildPath, "build", "WixToolset.Sdk.props");
22 22
23 public static MsbuildRunnerResult BuildProject(BuildSystem buildSystem, string projectPath, string[] arguments = null, string configuration = "Release", bool? outOfProc = null, string verbosityLevel = "normal") 23 public static MsbuildRunnerResult BuildProject(BuildSystem buildSystem, string projectPath, string[] arguments = null, string configuration = "Release", bool? outOfProc = null, string verbosityLevel = "normal", bool suppressValidation = true)
24 { 24 {
25 var allArgs = new List<string> 25 var allArgs = new List<string>
26 { 26 {
27 $"-verbosity:{verbosityLevel}", 27 $"-verbosity:{verbosityLevel}",
28 $"-p:Configuration={configuration}", 28 $"-p:Configuration={configuration}",
29 $"-p:SuppressValidation={suppressValidation}",
29 GetQuotedPropertySwitch(buildSystem, "WixMSBuildProps", MsbuildUtilities.WixPropsPath), 30 GetQuotedPropertySwitch(buildSystem, "WixMSBuildProps", MsbuildUtilities.WixPropsPath),
30 // Node reuse means that child msbuild processes can stay around after the build completes. 31 // Node reuse means that child msbuild processes can stay around after the build completes.
31 // Under that scenario, the root msbuild does not reliably close its streams which causes us to hang. 32 // Under that scenario, the root msbuild does not reliably close its streams which causes us to hang.
diff --git a/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/MsiPackage.wixproj b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/MsiPackage.wixproj
new file mode 100644
index 00000000..acbcd85d
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/MsiPackage.wixproj
@@ -0,0 +1,65 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <Import Project="$(WixMSBuildProps)" />
4 <PropertyGroup>
5 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6 <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
7 </PropertyGroup>
8
9 <PropertyGroup>
10 <ProjectGuid>7fb77005-c6e0-454f-8c2d-0a4a79c918ba</ProjectGuid>
11 </PropertyGroup>
12
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
14 <PlatformName>$(Platform)</PlatformName>
15 <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
16 <DefineConstants>Debug</DefineConstants>
17 </PropertyGroup>
18 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
19 <PlatformName>$(Platform)</PlatformName>
20 <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
21 </PropertyGroup>
22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
23 <PlatformName>$(Platform)</PlatformName>
24 <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
25 <DefineConstants>Debug</DefineConstants>
26 </PropertyGroup>
27 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
28 <PlatformName>$(Platform)</PlatformName>
29 <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
30 </PropertyGroup>
31
32 <ItemGroup>
33 <Compile Include="Package.wxs" />
34 <Compile Include="PackageComponents.wxs" />
35 </ItemGroup>
36
37 <ItemGroup>
38 <EmbeddedResource Include="Package.en-us.wxl" />
39 </ItemGroup>
40
41 <ItemGroup>
42 <BindInputPaths Include="data" />
43 </ItemGroup>
44
45 <Import Project="$(WixTargetsPath)" />
46
47 <Target Name="SignCabs">
48 <!-- It would be cool to actually sign, but signtool.exe is not always easy to find, so we'll
49 mock it up instead.
50 <Error Text="Could not find pfx at: $(TestCertificate)" Condition=" !Exists('$(TestCertificate)') " />
51 <Exec Command='signtool.exe sign /v /f $(TestCertificate) /p password %(SignCabs.FullPath)' />
52 -->
53 <Message Importance="high" Text="TEST: SignCabs: @(SignCabs)" />
54 </Target>
55
56 <Target Name="SignMsi">
57 <!-- It would be cool to actually sign, but signtool.exe is not always easy to find, so we'll
58 mock it up instead.
59 <Error Text="Could not find pfx at: $(TestCertificate)" Condition=" !Exists('$(TestCertificate)') " />
60 <Exec Command='signtool.exe sign /v /f $(TestCertificate) /p password "%(SignMsi.FullPath)" ' />
61 -->
62 <Message Importance="high" Text="TEST: SignMsi: @(SignMsi)" />
63 </Target>
64
65</Project>
diff --git a/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.en-us.wxl b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.en-us.wxl
new file mode 100644
index 00000000..38c12ac1
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.en-us.wxl
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4This file contains the declaration of all the localizable strings.
5-->
6<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
7
8 <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
9 <String Id="FeatureTitle">MsiPackage</String>
10
11</WixLocalization>
diff --git a/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.wxs b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.wxs
new file mode 100644
index 00000000..e187ed7b
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/Package.wxs
@@ -0,0 +1,26 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="yes" InstallerVersion="200">
3 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
5 <Property Id="MyProperty" Value="1" />
6 <Property Id="ReInStAlLmOdE" Value="Mixed-case Property Id causes ICE46" />
7
8 <Launch Condition="Myproperty" Message="Invalid cased Property Id below causes ICE46" />
9
10 <CustomAction Id="CausesICE12Error" Directory="INSTALLFOLDER" Value="Test" />
11
12 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
13 <ComponentGroupRef Id="ProductComponents" />
14 </Feature>
15
16 <InstallExecuteSequence>
17 <Custom Action="CausesICE12Error" Before="AppSearch" />
18 </InstallExecuteSequence>
19 </Package>
20
21 <Fragment>
22 <StandardDirectory Id="ProgramFiles6432Folder">
23 <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
24 </StandardDirectory>
25 </Fragment>
26</Wix>
diff --git a/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/PackageComponents.wxs b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/PackageComponents.wxs
new file mode 100644
index 00000000..e26c4509
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/PackageComponents.wxs
@@ -0,0 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment>
4 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
5 <Component>
6 <File Source="test.txt" />
7 </Component>
8 </ComponentGroup>
9 </Fragment>
10</Wix>
diff --git a/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/data/test.txt b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/data/test.txt
new file mode 100644
index 00000000..cd0db0e1
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithIceError/MsiPackage/data/test.txt
@@ -0,0 +1 @@
This is test.txt. \ No newline at end of file
diff --git a/src/wix/test/WixToolsetTest.Sdk/TestData/SimpleMsiPackage/MsiPackage/Package.wxs b/src/wix/test/WixToolsetTest.Sdk/TestData/SimpleMsiPackage/MsiPackage/Package.wxs
index 0a133c7d..30be1ace 100644
--- a/src/wix/test/WixToolsetTest.Sdk/TestData/SimpleMsiPackage/MsiPackage/Package.wxs
+++ b/src/wix/test/WixToolsetTest.Sdk/TestData/SimpleMsiPackage/MsiPackage/Package.wxs
@@ -12,7 +12,7 @@
12 </Package> 12 </Package>
13 13
14 <Fragment> 14 <Fragment>
15 <StandardDirectory Id="ProgramFilesFolder"> 15 <StandardDirectory Id="ProgramFiles6432Folder">
16 <Directory Id="INSTALLFOLDER" Name="MsiPackage" /> 16 <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
17 </StandardDirectory> 17 </StandardDirectory>
18 </Fragment> 18 </Fragment>