Expose bind variables from build command and via MSBuild WixVariables property
Also, resolves bind variables in path fields. Fixes 6995 and 7017
Rob Mensching committed
Nov 15, 2022 at 23:38 UTC
dd3ab394ec6e37c24827294605857730f8e7a1a5
27 files changed
+517
-123
src/api/wix/WixToolset.Data/ErrorMessages.cs
+12
-12
@@ -598,9 +598,9 @@ namespace WixToolset.Data
598
return Message(sourceLineNumbers, Ids.ExpectedVariable, "A required variable was missing in the expression '{0}'.", expression);
599
}
600
601
- public static Message ExpectedWixVariableValue(string variableId)
601
+ public static Message ExpectedBindVariableValue(string variableId)
602
{
603
- return Message(null, Ids.ExpectedWixVariableValue, "The WiX variable '{0}' was declared without a value. Please specify a value for the variable.", variableId);
603
+ return Message(null, Ids.ExpectedBindVariableValue, "The bind variable '{0}' was declared without a value. Please specify a value for the variable.", variableId);
604
}
605
606
public static Message FamilyNameTooLong(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value, int length)
@@ -1081,9 +1081,9 @@ namespace WixToolset.Data
1081
return Message(null, Ids.IllegalWarningIdAsError, "Illegal value '{0}' for the -wx<N> command line option. Specify a particular warning number, like '-wx6' to display the warning with ID 6 as an error, or '-wx' alone to suppress all warnings.", warningId);
1082
}
1083
1084
- public static Message IllegalWixVariablePrefix(SourceLineNumber sourceLineNumbers, string variableId)
1084
+ public static Message IllegalBindVariablePrefix(SourceLineNumber sourceLineNumbers, string variableId)
1085
{
1086
- return Message(sourceLineNumbers, Ids.IllegalWixVariablePrefix, "The WiX variable $(wix.{0}) uses an illegal prefix '$'. Please use the '!' prefix instead.", variableId);
1086
+ return Message(sourceLineNumbers, Ids.IllegalBindVariablePrefix, "The bind variable $(wix.{0}) uses an illegal prefix '$'. Please use the '!' prefix instead.", variableId);
1087
}
1088
1089
public static Message IllegalYesNoAlwaysValue(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value)
@@ -2231,14 +2231,14 @@ namespace WixToolset.Data
2231
return Message(null, Ids.WixFileNotFound, "The file '{0}' cannot be found.", file);
2232
}
2233
2234
- public static Message WixVariableCollision(SourceLineNumber sourceLineNumbers, string variableId)
2234
+ public static Message BindVariableCollision(SourceLineNumber sourceLineNumbers, string variableId)
2235
{
2236
- return Message(sourceLineNumbers, Ids.WixVariableCollision, "The WiX variable '{0}' is declared in more than one location. Please remove one of the declarations.", variableId);
2236
+ return Message(sourceLineNumbers, Ids.BindVariableCollision, "The bind variable '{0}' is declared in more than one location. Please remove one of the declarations.", variableId);
2237
}
2238
2239
- public static Message WixVariableUnknown(SourceLineNumber sourceLineNumbers, string variableId)
2239
+ public static Message BindVariableUnknown(SourceLineNumber sourceLineNumbers, string variableId)
2240
{
2241
- return Message(sourceLineNumbers, Ids.WixVariableUnknown, "The WiX variable !(wix.{0}) is unknown. Please ensure the variable is declared on the command line for light.exe, via a WixVariable element, or inline using the syntax !(wix.{0}=some value which doesn't contain parenthesis).", variableId);
2241
+ return Message(sourceLineNumbers, Ids.BindVariableUnknown, "The bind variable !(wix.{0}) is unknown. Please ensure the variable is declared on the command line for wix.exe, via a BindVariable element, or inline using the syntax !(wix.{0}=some value which doesn't contain parenthesis).", variableId);
2242
}
2243
2244
public static Message NoSourceFiles()
@@ -2474,10 +2474,10 @@ namespace WixToolset.Data
2474
VersionIndependentProgIdsCannotHaveIcons = 192,
2475
IllegalAttributeValueWithOtherAttribute = 193,
2476
InvalidMergeLanguage = 194,
2477
- WixVariableCollision = 195,
2478
- ExpectedWixVariableValue = 196,
2479
- WixVariableUnknown = 197,
2480
- IllegalWixVariablePrefix = 198,
2477
+ BindVariableCollision = 195,
2478
+ ExpectedBindVariableValue = 196,
2479
+ BindVariableUnknown = 197,
2480
+ IllegalBindVariablePrefix = 198,
2481
InvalidWixXmlNamespace = 199,
2482
UnhandledExtensionElement = 200,
2483
UnhandledExtensionAttribute = 201,
src/api/wix/WixToolset.Extensibility/Data/ILibraryContext.cs
+5
@@ -27,6 +27,11 @@ namespace WixToolset.Extensibility.Data
27
/// </summary>
28
IReadOnlyCollection<IBindPath> BindPaths { get; set; }
29
30
+ /// <summary>
31
+ /// Bind variables used when binding files.
32
+ /// </summary>
33
+ IDictionary<string, string> BindVariables { get; set; }
34
+
35
/// <summary>
36
/// Collection of extensions used during creation of library.
37
/// </summary>
src/api/wix/WixToolset.Extensibility/Data/IResolveContext.cs
+5
@@ -22,6 +22,11 @@ namespace WixToolset.Extensibility.Data
22
/// </summary>
23
IReadOnlyCollection<IBindPath> BindPaths { get; set; }
24
25
+ /// <summary>
26
+ /// Bind variables used during resolution.
27
+ /// </summary>
28
+ IDictionary<string, string> BindVariables { get; set; }
29
+
30
/// <summary>
31
/// Resolve extensions.
32
/// </summary>
src/wix/WixToolset.BuildTasks/WixBuild.cs
+22
@@ -45,6 +45,8 @@ namespace WixToolset.BuildTasks
45
46
public ITaskItem[] BindPaths { get; set; }
47
48
+ public ITaskItem[] BindVariables { get; set; }
49
+
50
public bool BindFiles { get; set; }
51
52
public ITaskItem BindTrackingFile { get; set; }
@@ -77,6 +79,7 @@ namespace WixToolset.BuildTasks
79
80
commandLineBuilder.AppendIfTrue("-bindFiles", this.BindFiles);
81
commandLineBuilder.AppendArrayIfNotNull("-bindPath ", this.CalculateBindPathStrings());
82
+ commandLineBuilder.AppendArrayIfNotNull("-bindVariable ", this.CalculateBindVariableStrings());
83
commandLineBuilder.AppendArrayIfNotNull("-loc ", this.LocalizationFiles);
84
commandLineBuilder.AppendArrayIfNotNull("-lib ", this.LibraryFiles);
85
commandLineBuilder.AppendTextIfNotWhitespace(this.AdditionalOptions);
@@ -103,5 +106,24 @@ namespace WixToolset.BuildTasks
106
}
107
}
108
}
109
+
110
+ private IEnumerable<string> CalculateBindVariableStrings()
111
+ {
112
+ if (null != this.BindVariables)
113
+ {
114
+ foreach (var item in this.BindVariables)
115
+ {
116
+ var value = item.ItemSpec;
117
+
118
+ var variableName = item.GetMetadata("Name");
119
+ if (!String.IsNullOrEmpty(variableName))
120
+ {
121
+ value = String.Concat(variableName, "=", value);
122
+ }
123
+
124
+ yield return value;
125
+ }
126
+ }
127
+ }
128
}
129
}
src/wix/WixToolset.Core/Bind/ResolveFieldsCommand.cs
+30
-20
@@ -88,25 +88,21 @@ namespace WixToolset.Core.Bind
88
89
var beforeErrorCount = this.Messaging.ErrorCount;
90
91
- // Check to make sure we're in a scenario where we can handle variable resolution.
92
- if (null != delayedFields)
91
+ // resolve localization and wix variables
92
+ if (fieldType == IntermediateFieldType.String)
93
{
94
- // resolve localization and wix variables
95
- if (fieldType == IntermediateFieldType.String)
94
+ var original = field.AsString();
95
+ if (!String.IsNullOrEmpty(original))
96
{
97
- var original = field.AsString();
98
- if (!String.IsNullOrEmpty(original))
97
+ var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, original, !this.AllowUnresolvedVariables);
98
+ if (resolution.UpdatedValue)
99
{
100
- var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, original, !this.AllowUnresolvedVariables);
101
- if (resolution.UpdatedValue)
102
- {
103
- field.Set(resolution.Value);
104
- }
105
-
106
- if (resolution.DelayedResolve)
107
- {
108
- delayedFields.Add(new DelayedField(symbol, field));
109
- }
100
+ field.Set(resolution.Value);
101
+ }
102
+
103
+ if (resolution.DelayedResolve)
104
+ {
105
+ delayedFields.Add(new DelayedField(symbol, field));
106
}
107
}
108
}
@@ -136,13 +132,27 @@ namespace WixToolset.Core.Bind
132
// If the file is embedded and if the previous value has a bind variable in the path
133
// which gets modified by resolving the previous value again then switch to that newly
134
// resolved path instead of using the embedded file.
139
- if (fieldValue.Embed && field.PreviousValue != null)
135
+ if (fieldValue.Embed)
136
+ {
137
+ if (field.PreviousValue != null)
138
+ {
139
+ var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, field.PreviousValue.AsString(), errorOnUnknown: false);
140
+
141
+ if (resolution.UpdatedValue && !resolution.IsDefault)
142
+ {
143
+ fieldValue = new IntermediateFieldPathValue { Path = resolution.Value };
144
+ }
145
+ }
146
+ }
147
+ else // resolve path field for bind variables.
148
{
141
- var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, field.PreviousValue.AsString(), errorOnUnknown: false);
149
+ var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, fieldValue.Path, errorOnUnknown: false);
150
143
- if (resolution.UpdatedValue && !resolution.IsDefault)
151
+ if (resolution.UpdatedValue)
152
{
145
- fieldValue = new IntermediateFieldPathValue { Path = resolution.Value };
153
+ field.Set(resolution.Value);
154
+
155
+ fieldValue = field.AsPath();
156
}
157
}
158
src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
+60
-21
@@ -10,6 +10,7 @@ namespace WixToolset.Core.CommandLine
10
using System.Threading.Tasks;
11
using System.Xml.Linq;
12
using WixToolset.Data;
13
+ using WixToolset.Data.Bind;
14
using WixToolset.Extensibility;
15
using WixToolset.Extensibility.Data;
16
using WixToolset.Extensibility.Services;
@@ -115,7 +116,7 @@ namespace WixToolset.Core.CommandLine
116
{
117
using (new IntermediateFieldContext("wix.lib"))
118
{
118
- this.LibraryPhase(wixobjs, wxls, inputsOutputs.LibraryPaths, creator, this.commandLine.BindFiles, this.commandLine.BindPaths, inputsOutputs.OutputPath, cancellationToken);
119
+ this.LibraryPhase(wixobjs, wxls, inputsOutputs.LibraryPaths, creator, this.commandLine.BindFiles, this.commandLine.BindPaths, this.commandLine.BindVariables, inputsOutputs.OutputPath, cancellationToken);
120
}
121
}
122
else
@@ -148,7 +149,7 @@ namespace WixToolset.Core.CommandLine
149
{
150
using (new IntermediateFieldContext("wix.bind"))
151
{
151
- this.BindPhase(wixipl, wxls, filterCultures, this.commandLine.CabCachePath, this.commandLine.CabbingThreadCount, this.commandLine.BindPaths, inputsOutputs, cancellationToken);
152
+ this.BindPhase(wixipl, wxls, filterCultures, this.commandLine.CabCachePath, this.commandLine.CabbingThreadCount, this.commandLine.BindPaths, this.commandLine.BindVariables, inputsOutputs, cancellationToken);
153
}
154
}
155
}
@@ -206,7 +207,7 @@ namespace WixToolset.Core.CommandLine
207
return intermediates;
208
}
209
209
- private void LibraryPhase(IReadOnlyCollection<Intermediate> intermediates, IReadOnlyCollection<Localization> localizations, IEnumerable<string> libraryFiles, ISymbolDefinitionCreator creator, bool bindFiles, IReadOnlyCollection<IBindPath> bindPaths, string outputPath, CancellationToken cancellationToken)
210
+ private void LibraryPhase(IReadOnlyCollection<Intermediate> intermediates, IReadOnlyCollection<Localization> localizations, IEnumerable<string> libraryFiles, ISymbolDefinitionCreator creator, bool bindFiles, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, string outputPath, CancellationToken cancellationToken)
211
{
212
var libraries = this.LoadLibraries(libraryFiles, creator);
213
@@ -218,6 +219,7 @@ namespace WixToolset.Core.CommandLine
219
var context = this.ServiceProvider.GetService<ILibraryContext>();
220
context.BindFiles = bindFiles;
221
context.BindPaths = bindPaths;
222
+ context.BindVariables = bindVariables;
223
context.Extensions = this.ExtensionManager.GetServices<ILibrarianExtension>();
224
context.Localizations = localizations;
225
context.IntermediateFolder = this.IntermediateFolder;
@@ -266,12 +268,13 @@ namespace WixToolset.Core.CommandLine
268
return linker.Link(context);
269
}
270
269
- private void BindPhase(Intermediate output, IReadOnlyCollection<Localization> localizations, IReadOnlyCollection<string> filterCultures, string cabCachePath, int cabbingThreadCount, IReadOnlyCollection<IBindPath> bindPaths, InputsAndOutputs inputsOutputs, CancellationToken cancellationToken)
271
+ private void BindPhase(Intermediate output, IReadOnlyCollection<Localization> localizations, IReadOnlyCollection<string> filterCultures, string cabCachePath, int cabbingThreadCount, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, InputsAndOutputs inputsOutputs, CancellationToken cancellationToken)
272
{
273
IResolveResult resolveResult;
274
{
275
var context = this.ServiceProvider.GetService<IResolveContext>();
276
context.BindPaths = bindPaths;
277
+ context.BindVariables = bindVariables;
278
context.Extensions = this.ExtensionManager.GetServices<IResolverExtension>();
279
context.ExtensionData = this.ExtensionManager.GetServices<IExtensionData>();
280
context.FilterCultures = filterCultures;
@@ -466,6 +469,8 @@ namespace WixToolset.Core.CommandLine
469
470
public List<IBindPath> BindPaths { get; } = new List<IBindPath>();
471
472
+ public Dictionary<string, string> BindVariables { get; } = new Dictionary<string, string>();
473
+
474
public string CabCachePath { get; private set; }
475
476
public int CabbingThreadCount { get; private set; }
@@ -564,6 +569,24 @@ namespace WixToolset.Core.CommandLine
569
return true;
570
}
571
572
+ case "bv":
573
+ case "bindvariable":
574
+ {
575
+ var value = parser.GetNextArgumentOrError(arg);
576
+ if (value != null && TryParseNameValuePair(value, out var parsedName, out var parsedValue))
577
+ {
578
+ if (this.BindVariables.TryGetValue(parsedName, out var collisionValue))
579
+ {
580
+ parser.ReportErrorArgument(arg, LinkerErrors.DuplicateBindPathVariableOnCommandLine(arg, parsedName, parsedValue, collisionValue));
581
+ }
582
+ else
583
+ {
584
+ this.BindVariables.Add(parsedName, parsedValue);
585
+ }
586
+ }
587
+ return true;
588
+ }
589
+
590
case "cc":
591
case "cabcache":
592
this.CabCachePath = parser.GetNextArgumentOrError(arg);
@@ -651,20 +674,20 @@ namespace WixToolset.Core.CommandLine
674
return true;
675
676
case "pdbtype":
677
+ {
678
+ var value = parser.GetNextArgumentOrError(arg);
679
+ if (Enum.TryParse(value, true, out PdbType pdbType))
680
{
655
- var value = parser.GetNextArgumentOrError(arg);
656
- if (Enum.TryParse(value, true, out PdbType pdbType))
657
- {
658
- this.PdbType = pdbType;
659
- }
660
- else if (!String.IsNullOrEmpty(value))
661
- {
662
- parser.ReportErrorArgument(arg, ErrorMessages.IllegalCommandLineArgumentValue(arg, value, Enum.GetNames(typeof(PdbType)).Select(s => s.ToLowerInvariant())));
663
- }
664
-
665
- return true;
681
+ this.PdbType = pdbType;
682
+ }
683
+ else if (!String.IsNullOrEmpty(value))
684
+ {
685
+ parser.ReportErrorArgument(arg, ErrorMessages.IllegalCommandLineArgumentValue(arg, value, Enum.GetNames(typeof(PdbType)).Select(s => s.ToLowerInvariant())));
686
}
687
688
+ return true;
689
+ }
690
+
691
case "resetacls":
692
this.ResetAcls = true;
693
return true;
@@ -870,18 +893,16 @@ namespace WixToolset.Core.CommandLine
893
894
private bool TryParseBindPath(string argument, string bindPath, out IBindPath bp)
895
{
873
- var namedPath = bindPath.Split(BindPathSplit, 2);
874
-
896
bp = this.ServiceProvider.GetService<IBindPath>();
897
877
- if (1 == namedPath.Length)
898
+ if (TryParseNameValuePair(bindPath, out var name, out var path))
899
{
879
- bp.Path = namedPath[0];
900
+ bp.Name = name;
901
+ bp.Path = path;
902
}
903
else
904
{
883
- bp.Name = namedPath[0];
884
- bp.Path = namedPath[1];
905
+ bp.Path = bindPath;
906
}
907
908
if (File.Exists(bp.Path))
@@ -892,6 +913,24 @@ namespace WixToolset.Core.CommandLine
913
914
return true;
915
}
916
+
917
+ private static bool TryParseNameValuePair(string nameValuePair, out string key, out string value)
918
+ {
919
+ var split = nameValuePair.Split(BindPathSplit, 2);
920
+
921
+ if (1 == split.Length)
922
+ {
923
+ key = null;
924
+ value = null;
925
+
926
+ return false;
927
+ }
928
+
929
+ key = split[0];
930
+ value = split[1];
931
+
932
+ return true;
933
+ }
934
}
935
936
private class InputsAndOutputs
src/wix/WixToolset.Core/Librarian.cs
+5
@@ -99,6 +99,11 @@ namespace WixToolset.Core
99
{
100
var variableResolver = this.ServiceProvider.GetService<IVariableResolver>();
101
102
+ foreach (var bindVariable in context.BindVariables)
103
+ {
104
+ variableResolver.AddVariable(null, bindVariable.Key, bindVariable.Value, false);
105
+ }
106
+
107
var bindPaths = context.BindPaths.Where(b => b.Stage == BindStage.Normal).ToList();
108
109
foreach (var symbol in sections.SelectMany(s => s.Symbols))
src/wix/WixToolset.Core/LibraryContext.cs
+2
@@ -25,6 +25,8 @@ namespace WixToolset.Core
25
26
public IReadOnlyCollection<IBindPath> BindPaths { get; set; }
27
28
+ public IDictionary<string, string> BindVariables { get; set; }
29
+
30
public IReadOnlyCollection<ILibrarianExtension> Extensions { get; set; }
31
32
public string LibraryId { get; set; }
src/wix/WixToolset.Core/Linker.cs
+1
-1
@@ -333,7 +333,7 @@ namespace WixToolset.Core
333
}
334
else if (!symbol.Overridable || (collidingSymbol.Overridable && symbol.Overridable))
335
{
336
- this.Messaging.Write(ErrorMessages.WixVariableCollision(symbol.SourceLineNumbers, id));
336
+ this.Messaging.Write(ErrorMessages.BindVariableCollision(symbol.SourceLineNumbers, id));
337
}
338
}
339
else
src/wix/WixToolset.Core/LinkerErrors.cs
+6
@@ -6,6 +6,11 @@ namespace WixToolset.Core
6
7
internal static class LinkerErrors
8
{
9
+ public static Message DuplicateBindPathVariableOnCommandLine(string argument, string bindName, string bindValue, string collisionValue)
10
+ {
11
+ return Message(null, Ids.DuplicateBindPathVariableOnCommandLine, "", argument, bindName, bindValue, collisionValue);
12
+ }
13
+
14
public static Message OrphanedPayload(SourceLineNumber sourceLineNumbers, string payloadId)
15
{
16
return Message(sourceLineNumbers, Ids.OrphanedPayload, "Found orphaned Payload '{0}'. Make sure to reference it from a Package, the BootstrapperApplication, or the Bundle or move it into its own Fragment so it only gets linked in when actually used.", payloadId);
@@ -55,6 +60,7 @@ namespace WixToolset.Core
60
UnscheduledRollbackBoundary = 7004,
61
UncompressedPayloadInContainer = 7005,
62
BAContainerCannotContainRemotePayload = 7006,
63
+ DuplicateBindPathVariableOnCommandLine = 7007,
64
} // last available is 7099. 7100 is WindowsInstallerBackendWarnings.
65
}
66
}
src/wix/WixToolset.Core/ResolveContext.cs
+3
-4
@@ -8,8 +8,7 @@ namespace WixToolset.Core
8
using WixToolset.Data;
9
using WixToolset.Extensibility;
10
using WixToolset.Extensibility.Data;
11
- using WixToolset.Extensibility.Services;
12
-
11
+
12
internal class ResolveContext : IResolveContext
13
{
14
internal ResolveContext(IServiceProvider serviceProvider)
@@ -21,6 +20,8 @@ namespace WixToolset.Core
20
21
public IReadOnlyCollection<IBindPath> BindPaths { get; set; }
22
23
+ public IDictionary<string, string> BindVariables { get; set; }
24
+
25
public IReadOnlyCollection<IResolverExtension> Extensions { get; set; }
26
27
public IReadOnlyCollection<IExtensionData> ExtensionData { get; set; }
@@ -33,8 +34,6 @@ namespace WixToolset.Core
34
35
public IReadOnlyCollection<Localization> Localizations { get; set; }
36
36
- public IVariableResolver VariableResolver { get; set; }
37
-
37
public bool AllowUnresolvedVariables { get; set; }
38
39
public string OutputPath { get; set; }
src/wix/WixToolset.Core/Resolver.cs
+5
@@ -187,6 +187,11 @@ namespace WixToolset.Core
187
variableResolver.AddLocalization(localization);
188
}
189
190
+ foreach (var bindVariable in context.BindVariables)
191
+ {
192
+ variableResolver.AddVariable(null, bindVariable.Key, bindVariable.Value, false);
193
+ }
194
+
195
// Gather all the wix variables.
196
var wixVariableSymbols = context.IntermediateRepresentation.Sections.SelectMany(s => s.Symbols).OfType<WixVariableSymbol>();
197
foreach (var symbol in wixVariableSymbols)
src/wix/WixToolset.Core/VariableResolver.cs
+3
-6
@@ -23,7 +23,6 @@ namespace WixToolset.Core
23
/// </summary>
24
internal VariableResolver(IServiceProvider serviceProvider)
25
{
26
- this.ServiceProvider = serviceProvider;
26
this.Messaging = serviceProvider.GetService<IMessaging>();
27
28
this.locVariables = new Dictionary<string, BindVariable>();
@@ -31,8 +30,6 @@ namespace WixToolset.Core
30
this.localizedControls = new Dictionary<string, LocalizedControl>();
31
}
32
34
- private IServiceProvider ServiceProvider { get; }
35
-
33
private IMessaging Messaging { get; }
34
35
public int VariableCount => this.wixVariables.Count;
@@ -47,7 +44,7 @@ namespace WixToolset.Core
44
}
45
}
46
50
- foreach (KeyValuePair<string, LocalizedControl> localizedControl in localization.LocalizedControls)
47
+ foreach (var localizedControl in localization.LocalizedControls)
48
{
49
if (!this.localizedControls.ContainsKey(localizedControl.Key))
50
{
@@ -62,7 +59,7 @@ namespace WixToolset.Core
59
60
if (!TryAddWixVariable(this.wixVariables, bindVariable))
61
{
65
- this.Messaging.Write(ErrorMessages.WixVariableCollision(sourceLineNumber, name));
62
+ this.Messaging.Write(ErrorMessages.BindVariableCollision(sourceLineNumber, name));
63
}
64
}
65
@@ -166,7 +163,7 @@ namespace WixToolset.Core
163
}
164
else if ("wix" == variableNamespace && errorOnUnknown) // unresolved wix variable
165
{
169
- this.Messaging.Write(ErrorMessages.WixVariableUnknown(sourceLineNumbers, variableId));
166
+ this.Messaging.Write(ErrorMessages.BindVariableUnknown(sourceLineNumbers, variableId));
167
}
168
169
start = parsed.Index + parsed.Length;
src/wix/WixToolset.Sdk/tools/wix.targets
+3
-1
@@ -41,7 +41,7 @@
41
</ItemGroup>
42
43
<ItemGroup>
44
- <AvailableItemName Include="BindPath;WixLibrary;WixExtension" />
44
+ <AvailableItemName Include="BindPath;BindVariable;WixLibrary;WixExtension" />
45
</ItemGroup>
46
47
<!--
@@ -170,6 +170,7 @@
170
<LinkerBindInputPaths Include="$(LinkerBindInputPaths)" Condition=" '$(LinkerBindInputPaths)' != '' " />
171
<BindPath Include="$(BindPath)" Condition=" '$(BindPath)' != '' " />
172
<BindPath Include="@(BindInputPaths);@(LinkerBindInputPaths)" />
173
+ <BindVariable Include="$(WixVariables)" Condition=" '$(WixVariables)' != '' " />
174
</ItemGroup>
175
176
<!--
@@ -601,6 +602,7 @@
602
Pedantic="$(Pedantic)"
603
604
BindPaths="@(BindPath)"
605
+ BindVariables="@(BindVariable)"
606
BindFiles="$(BindFiles)"
607
BindTrackingFile="$(IntermediateOutputPath)$(BindTrackingFilePrefix)%(CultureGroup.Identity)$(BindTrackingFileExtension)"
608
src/wix/test/WixToolsetTest.Core/VariableResolverFixture.cs
renamed
+2
-3
@@ -1,7 +1,6 @@
1
-
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
4
-namespace WixToolsetTest.CoreIntegration
3
+namespace WixToolsetTest.Core
4
{
5
using System.Collections.Generic;
6
using WixInternal.TestSupport;
@@ -26,7 +25,7 @@ namespace WixToolsetTest.CoreIntegration
25
{ "ProductNameEditionVersion", new BindVariable() { Id = "ProductNameEditionVersion", Value = "!(loc.ProductNameEdition) v1.2.3" } },
26
};
27
29
- var localization = new Localization(0, null, "x-none", variables, new Dictionary<string,LocalizedControl>());
28
+ var localization = new Localization(0, null, "x-none", variables, new Dictionary<string, LocalizedControl>());
29
30
variableResolver.AddLocalization(localization);
31
src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixVariable/Bundle.wxs
new
+11
@@ -0,0 +1,11 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Bundle Name="MsiPackage-Bundle" Version="!(wix.VersionVar)" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <BootstrapperApplication>
4
+ <BootstrapperApplicationDll SourceFile="fakeba.dll" />
5
+ </BootstrapperApplication>
6
+
7
+ <Chain>
8
+ <MsiPackage SourceFile="test1.msi" />
9
+ </Chain>
10
+ </Bundle>
11
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixVariable/PackageWithBindVariableVersion.wxs
new
+33
@@ -0,0 +1,33 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Version="!(wix.VersionVar)"
3
+ Name="MsiPackage"
4
+ Manufacturer="Example Corporation"
5
+ UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"
6
+ Scope="perUser">
7
+ <MajorUpgrade DowngradeErrorMessage="Downgrade not allowed" />
8
+ <MediaTemplate EmbedCab="true" />
9
+
10
+ <Feature Id="ProductFeature" Title="Feature title">
11
+ <ComponentGroupRef Id="ProductComponents" />
12
+ </Feature>
13
+
14
+ <WixVariable Id="VersionVar" Value="v1.1.1.1" Overridable="true" />
15
+ </Package>
16
+
17
+ <Fragment>
18
+ <StandardDirectory Id="DesktopFolder">
19
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage !(wix.VersionVar) and !(bind.property.ProductVersion)" />
20
+ </StandardDirectory>
21
+ </Fragment>
22
+
23
+ <Fragment>
24
+ <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
25
+ <Component>
26
+ <File Source="test.txt" />
27
+ </Component>
28
+ <Component Id="Shared.dll" Shared="yes">
29
+ <File Name="Shared.dll" Source="test.txt" />
30
+ </Component>
31
+ </ComponentGroup>
32
+ </Fragment>
33
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixVariable/PackageWithReplaceableVersion.wxs
new
+22
@@ -0,0 +1,22 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Version="!(wix.VersionVar)"
3
+ Name="MsiPackage"
4
+ Manufacturer="Example Corporation"
5
+ UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"
6
+ Scope="perUser">
7
+ <MajorUpgrade DowngradeErrorMessage="Downgrade not allowed" />
8
+ <MediaTemplate EmbedCab="true" />
9
+
10
+ <Feature Id="ProductFeature" Title="Feature title">
11
+ <Component Directory="INSTALLFOLDER">
12
+ <File Source="!(wix.DataBindVariable)\test.txt" />
13
+ </Component>
14
+ </Feature>
15
+ </Package>
16
+
17
+ <Fragment>
18
+ <StandardDirectory Id="DesktopFolder">
19
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage !(wix.VersionVar)" />
20
+ </StandardDirectory>
21
+ </Fragment>
22
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/WixVariableFixture.cs
new
+174
@@ -0,0 +1,174 @@
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 WixToolsetTest.CoreIntegration
4
+{
5
+ using System.IO;
6
+ using System.Linq;
7
+ using System.Xml;
8
+ using WixInternal.Core.TestPackage;
9
+ using WixInternal.TestSupport;
10
+ using Xunit;
11
+
12
+ public class WixVariableFixture
13
+ {
14
+ [Fact]
15
+ public void CanBuildMsiWithBindVariable()
16
+ {
17
+ var folder = TestData.Get(@"TestData");
18
+
19
+ using (var fs = new DisposableFileSystem())
20
+ {
21
+ var baseFolder = fs.GetFolder();
22
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
23
+ var msiPath = Path.Combine(baseFolder, "bin", "test1.msi");
24
+
25
+ var result = WixRunner.Execute(new[]
26
+ {
27
+ "build",
28
+ Path.Combine(folder, "WixVariable", "PackageWithReplaceableVersion.wxs"),
29
+ "-bindpath", Path.Combine(folder, "SingleFile"/*, this part of the path is added as a bind variable: "data"*/),
30
+ "-bindvariable", "DataBindVariable=data",
31
+ "-bindvariable", "VersionVar=4.3.2.1",
32
+ "-intermediateFolder", intermediateFolder,
33
+ "-o", msiPath
34
+ });
35
+
36
+ result.AssertSuccess();
37
+
38
+ var productVersion = GetProductVersionFromMsi(msiPath);
39
+ Assert.Equal("4.3.2.1", productVersion);
40
+ }
41
+ }
42
+
43
+ [Fact]
44
+ public void CanBuildMsiWithDefaultedBindVariable()
45
+ {
46
+ var folder = TestData.Get(@"TestData");
47
+
48
+ using (var fs = new DisposableFileSystem())
49
+ {
50
+ var baseFolder = fs.GetFolder();
51
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
52
+ var msiPath = Path.Combine(baseFolder, "bin", "test1.msi");
53
+
54
+ var result = WixRunner.Execute(new[]
55
+ {
56
+ "build",
57
+ Path.Combine(folder, "WixVariable", "PackageWithBindVariableVersion.wxs"),
58
+ "-bindpath", Path.Combine(folder, "SingleFile", "data"),
59
+ "-intermediateFolder", intermediateFolder,
60
+ "-o", msiPath
61
+ });
62
+
63
+ result.AssertSuccess();
64
+
65
+ var productVersion = GetProductVersionFromMsi(msiPath);
66
+ Assert.Equal("1.1.1.1", productVersion);
67
+
68
+ var directoryTable = Query.QueryDatabase(msiPath, new[] { "Directory" }).OrderBy(s => s).ToArray();
69
+ WixAssert.CompareLineByLine(new[]
70
+ {
71
+ "Directory:DesktopFolder\tTARGETDIR\tDesktop",
72
+ "Directory:INSTALLFOLDER\tDesktopFolder\tfcuah1wu|MsiPackage v1.1.1.1 and 1.1.1.1",
73
+ "Directory:TARGETDIR\t\tSourceDir"
74
+ }, directoryTable);
75
+ }
76
+ }
77
+
78
+ [Fact]
79
+ public void CanBuildMsiWithPrefixedVersionBindVariable()
80
+ {
81
+ var folder = TestData.Get(@"TestData");
82
+
83
+ using (var fs = new DisposableFileSystem())
84
+ {
85
+ var baseFolder = fs.GetFolder();
86
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
87
+ var msiPath = Path.Combine(baseFolder, "bin", "test1.msi");
88
+
89
+ var result = WixRunner.Execute(new[]
90
+ {
91
+ "build",
92
+ Path.Combine(folder, "WixVariable", "PackageWithBindVariableVersion.wxs"),
93
+ "-bindpath", Path.Combine(folder, "SingleFile", "data"),
94
+ "-intermediateFolder", intermediateFolder,
95
+ "-bindvariable", "VersionVar=v9.8.7.6",
96
+ "-o", msiPath
97
+ });
98
+
99
+ result.AssertSuccess();
100
+
101
+ var productVersion = GetProductVersionFromMsi(msiPath);
102
+ Assert.Equal("9.8.7.6", productVersion);
103
+
104
+ var directoryTable = Query.QueryDatabase(msiPath, new[] { "Directory" }).OrderBy(s => s).ToArray();
105
+ WixAssert.CompareLineByLine(new[]
106
+ {
107
+ "Directory:DesktopFolder\tTARGETDIR\tDesktop",
108
+ "Directory:INSTALLFOLDER\tDesktopFolder\tpja2bznq|MsiPackage v9.8.7.6 and 9.8.7.6",
109
+ "Directory:TARGETDIR\t\tSourceDir"
110
+ }, directoryTable);
111
+ }
112
+ }
113
+
114
+ [Fact]
115
+ public void CanBuildBundleWithBindVariable()
116
+ {
117
+ var folder = TestData.Get(@"TestData");
118
+
119
+ using (var fs = new DisposableFileSystem())
120
+ {
121
+ var baseFolder = fs.GetFolder();
122
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
123
+ var msiPath = Path.Combine(baseFolder, "bin", "test1.msi");
124
+ var msi2Path = Path.Combine(baseFolder, "bin", "test2.msi");
125
+ var bundlePath = Path.Combine(baseFolder, "bin", "bundle.exe");
126
+
127
+ var result = WixRunner.Execute(new[]
128
+ {
129
+ "build",
130
+ Path.Combine(folder, "WixVariable", "PackageWithReplaceableVersion.wxs"),
131
+ "-bindpath", Path.Combine(folder, "SingleFile"/*, this part of the path is added as a bind variable: "data"*/),
132
+ "-bv", "DataBindVariable=data",
133
+ "-bv", "VersionVar=255.255.65535",
134
+ "-intermediateFolder", intermediateFolder,
135
+ "-o", msiPath
136
+ });
137
+
138
+ result.AssertSuccess();
139
+
140
+ var result3 = WixRunner.Execute(new[]
141
+{
142
+ "build",
143
+ Path.Combine(folder, "WixVariable", "Bundle.wxs"),
144
+ "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
145
+ "-bindpath", Path.Combine(baseFolder, "bin"),
146
+ "-intermediateFolder", intermediateFolder,
147
+ "-bv", "VersionVar=2022.3.9-preview.0-build.5+0987654321abcdef1234567890",
148
+ "-o", bundlePath
149
+ });
150
+
151
+ result3.AssertSuccess();
152
+
153
+ var productVersion = GetProductVersionFromMsi(msiPath);
154
+ WixAssert.StringEqual("255.255.65535", productVersion);
155
+
156
+ var extractResult = BundleExtractor.ExtractAllContainers(null, bundlePath, Path.Combine(baseFolder, "ba"), Path.Combine(baseFolder, "attached"), Path.Combine(baseFolder, "extract"));
157
+ extractResult.AssertSuccess();
158
+
159
+ var bundleVersion = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Registration/@Version")
160
+ .Cast<XmlAttribute>()
161
+ .Single();
162
+ WixAssert.StringEqual("2022.3.9-preview.0-build.5+0987654321abcdef1234567890", bundleVersion.Value);
163
+ }
164
+ }
165
+
166
+ private static string GetProductVersionFromMsi(string msiPath)
167
+ {
168
+ var propertyTable = Query.QueryDatabase(msiPath, new[] { "Property" }).Select(r => r.Split('\t')).ToDictionary(r => r[0].Substring("Property:".Length), r => r[1]);
169
+ Assert.True(propertyTable.TryGetValue("ProductVersion", out var productVersion));
170
+
171
+ return productVersion;
172
+ }
173
+ }
174
+}
src/wix/test/WixToolsetTest.Sdk/MsbuildFixture.cs
+64
-28
@@ -229,6 +229,42 @@ namespace WixToolsetTest.Sdk
229
}
230
}
231
232
+ [Theory]
233
+ [InlineData(BuildSystem.DotNetCoreSdk)]
234
+ [InlineData(BuildSystem.MSBuild)]
235
+ [InlineData(BuildSystem.MSBuild64)]
236
+ public void CanBuildMsiPackageWithBindVariables(BuildSystem buildSystem)
237
+ {
238
+ var sourceFolder = TestData.Get("TestData", "MsiPackageWithBindVariables");
239
+
240
+ var baseFolder = String.Empty;
241
+
242
+ using (var fs = new TestDataFolderFileSystem())
243
+ {
244
+ fs.Initialize(sourceFolder);
245
+ baseFolder = fs.BaseFolder;
246
+
247
+ var binFolder = Path.Combine(baseFolder, @"bin\");
248
+ var projectPath = Path.Combine(baseFolder, "MsiPackageWithBindVariables.wixproj");
249
+
250
+ var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[] {
251
+ MsbuildUtilities.GetQuotedPropertySwitch(buildSystem, "WixMSBuildProps", MsbuildFixture.WixPropsPath)
252
+ });
253
+ result.AssertSuccess();
254
+
255
+ var paths = Directory.EnumerateFiles(binFolder, @"*.*", SearchOption.AllDirectories)
256
+ .Select(s => s.Substring(baseFolder.Length + 1))
257
+ .OrderBy(s => s)
258
+ .ToArray();
259
+ WixAssert.CompareLineByLine(new[]
260
+ {
261
+ @"bin\Release\en-US\cab1.cab",
262
+ @"bin\Release\en-US\MsiPackageWithBindVariables.msi",
263
+ @"bin\Release\en-US\MsiPackageWithBindVariables.wixpdb",
264
+ }, paths);
265
+ }
266
+ }
267
+
268
[Theory]
269
[InlineData(BuildSystem.DotNetCoreSdk)]
270
[InlineData(BuildSystem.MSBuild)]
@@ -299,33 +335,6 @@ namespace WixToolsetTest.Sdk
335
}
336
}
337
302
- private void AssertWixpdb(BuildSystem buildSystem, string debugType, string[] expectedOutputFiles)
303
- {
304
- var sourceFolder = TestData.Get(@"TestData\SimpleMsiPackage\MsiPackage");
305
-
306
- using (var fs = new TestDataFolderFileSystem())
307
- {
308
- fs.Initialize(sourceFolder);
309
- var baseFolder = fs.BaseFolder;
310
- var binFolder = Path.Combine(baseFolder, @"bin\");
311
- var projectPath = Path.Combine(baseFolder, "MsiPackage.wixproj");
312
-
313
- var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[]
314
- {
315
- MsbuildUtilities.GetQuotedPropertySwitch(buildSystem, "WixMSBuildProps", MsbuildFixture.WixPropsPath),
316
- debugType == null ? String.Empty : $"-p:DebugType={debugType}",
317
- "-p:SuppressValidation=true"
318
- });
319
- result.AssertSuccess();
320
-
321
- var paths = Directory.EnumerateFiles(binFolder, @"*.*", SearchOption.AllDirectories)
322
- .Select(s => s.Substring(baseFolder.Length + 1))
323
- .OrderBy(s => s)
324
- .ToArray();
325
- WixAssert.CompareLineByLine(expectedOutputFiles, paths);
326
- }
327
- }
328
-
338
[Theory]
339
[InlineData(BuildSystem.DotNetCoreSdk)]
340
[InlineData(BuildSystem.MSBuild)]
@@ -474,7 +483,7 @@ namespace WixToolsetTest.Sdk
483
var path = Directory.EnumerateFiles(binFolder, @"*.*", SearchOption.AllDirectories)
484
.Select(s => s.Substring(baseFolder.Length + 1))
485
.Single();
477
- WixAssert.StringEqual(@"bin\x86\Release\SimpleWixlib.wixlib", path);
486
+ WixAssert.StringEqual(@"bin\Release\SimpleWixlib.wixlib", path);
487
}
488
}
489
@@ -637,6 +646,33 @@ namespace WixToolsetTest.Sdk
646
}
647
}
648
649
+ private void AssertWixpdb(BuildSystem buildSystem, string debugType, string[] expectedOutputFiles)
650
+ {
651
+ var sourceFolder = TestData.Get(@"TestData\SimpleMsiPackage\MsiPackage");
652
+
653
+ using (var fs = new TestDataFolderFileSystem())
654
+ {
655
+ fs.Initialize(sourceFolder);
656
+ var baseFolder = fs.BaseFolder;
657
+ var binFolder = Path.Combine(baseFolder, @"bin\");
658
+ var projectPath = Path.Combine(baseFolder, "MsiPackage.wixproj");
659
+
660
+ var result = MsbuildUtilities.BuildProject(buildSystem, projectPath, new[]
661
+ {
662
+ MsbuildUtilities.GetQuotedPropertySwitch(buildSystem, "WixMSBuildProps", MsbuildFixture.WixPropsPath),
663
+ debugType == null ? String.Empty : $"-p:DebugType={debugType}",
664
+ "-p:SuppressValidation=true"
665
+ });
666
+ result.AssertSuccess();
667
+
668
+ var paths = Directory.EnumerateFiles(binFolder, @"*.*", SearchOption.AllDirectories)
669
+ .Select(s => s.Substring(baseFolder.Length + 1))
670
+ .OrderBy(s => s)
671
+ .ToArray();
672
+ WixAssert.CompareLineByLine(expectedOutputFiles, paths);
673
+ }
674
+ }
675
+
676
private static string ExtractWarningFromMessage(string message, string baseFolder)
677
{
678
const string prefix = ": warning ";
src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithBindVariables/MsiPackageWithBindVariables.wixproj
new
+16
@@ -0,0 +1,16 @@
1
+<Project>
2
+ <Import Project="$(WixMSBuildProps)" />
3
+ <PropertyGroup>
4
+ <WixVariables>DataFolderVar=data</WixVariables>
5
+ </PropertyGroup>
6
+
7
+ <ItemGroup>
8
+ <Compile Include="Package.wxs" />
9
+
10
+ <EmbeddedResource Include="Package.en-us.wxl" />
11
+
12
+ <BindVariable Include="VersionVar=1.2.3" />
13
+ </ItemGroup>
14
+
15
+ <Import Project="$(WixTargetsPath)" />
16
+</Project>
src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithBindVariables/Package.en-us.wxl
new
+11
@@ -0,0 +1,11 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+
3
+<!--
4
+This 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" Value="A newer version of [ProductName] is already installed." />
9
+ <String Id="FeatureTitle" Value="MsiPackage" />
10
+
11
+</WixLocalization>
src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithBindVariables/Package.wxs
new
+17
@@ -0,0 +1,17 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Language="1033" Version="!(wix.VersionVar)" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
+
5
+ <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
6
+ <Component Directory="INSTALLFOLDER">
7
+ <File Source="!(wix.DataFolderVar)\test.txt" />
8
+ </Component>
9
+ </Feature>
10
+ </Package>
11
+
12
+ <Fragment>
13
+ <StandardDirectory Id="ProgramFiles6432Folder">
14
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
15
+ </StandardDirectory>
16
+ </Fragment>
17
+</Wix>
src/wix/test/WixToolsetTest.Sdk/TestData/MsiPackageWithBindVariables/data/test.txt
new
+1
@@ -0,0 +1 @@
1
+This is test.txt.
\ No newline at end of file
src/wix/test/WixToolsetTest.Sdk/TestData/Wixlib/SimpleWixlib/Library.wxs
+1
-1
@@ -8,7 +8,7 @@
8
<Fragment>
9
<ComponentGroup Id="ProductComponents" Directory="WixLibFolder">
10
<Component Id="TextFile" Guid="2D93B748-4926-4185-BC84-9F1D6883AF20">
11
- <File Source="Library.txt" />
11
+ <File Source="!(wix.SubfolderVar)\Library.txt" />
12
</Component>
13
</ComponentGroup>
14
</Fragment>
src/wix/test/WixToolsetTest.Sdk/TestData/Wixlib/SimpleWixlib/SimpleWixlib.wixproj
+3
-26
@@ -1,34 +1,11 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
-<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2
+<Project>
3
<Import Project="$(WixMSBuildProps)" />
4
+
5
<PropertyGroup>
5
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6
- <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
6
<OutputType>Library</OutputType>
7
<BindFiles>true</BindFiles>
9
- </PropertyGroup>
10
-
11
- <PropertyGroup>
12
- <ProjectGuid>{9F84998B-7F45-4CB3-8795-915801DBBB74}</ProjectGuid>
13
- </PropertyGroup>
14
-
15
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
16
- <PlatformName>$(Platform)</PlatformName>
17
- <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
18
- <DefineConstants>Debug</DefineConstants>
19
- </PropertyGroup>
20
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
21
- <PlatformName>$(Platform)</PlatformName>
22
- <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
23
- </PropertyGroup>
24
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
25
- <PlatformName>$(Platform)</PlatformName>
26
- <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
27
- <DefineConstants>Debug</DefineConstants>
28
- </PropertyGroup>
29
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
30
- <PlatformName>$(Platform)</PlatformName>
31
- <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
8
+ <WixVariables>SubfolderVar=subfolder</WixVariables>
9
</PropertyGroup>
10
11
<ItemGroup>