Support naked files.
Implements https://github.com/wixtoolset/issues/issues/7696. `File` elements can appear where `Component` elements do in WiX v4. The compiler generates an appropriate per-file component. Naked files under `Directory`, `DirectoryRef`, `Fragment`, `StandardDirectory`, or `Package` elements are included in a package via the [default-feature feature](https://github.com/wixtoolset/issues/issues/7581). Naked files appearing under `ComponentGroup`, `Feature`, `FeatureRef`, and `FeatureGroup` generate the component and the reference to the parent element. Components and naked Files default to being installed to INSTALLFOLDER (including a default INSTALLFOLDER if one isn't otherwise authored).
Bob Arnson committed
Sep 10, 2023 at 22:34 UTC
f676ceeaedbba4125d3e0c691959afcba182d008
27 files changed
+751
-120
src/api/wix/WixToolset.Data/ErrorMessages.cs
+5
@@ -2256,6 +2256,11 @@ namespace WixToolset.Data
2256
return Message(sourceLineNumbers, Ids.IllegalInnerText, "The {0} element contains inner text which is obsolete. Use the {1} attribute instead.", elementName, attributeName);
2257
}
2258
2259
+ public static Message IllegalAttributeWhenNested(SourceLineNumber sourceLineNumbers, string attributeName)
2260
+ {
2261
+ return Message(sourceLineNumbers, Ids.IllegalAttributeWhenNested, "The File element contains an attribute '{0}' that cannot be used in a File element that is a child of a Component element.", attributeName);
2262
+ }
2263
+
2264
private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
2265
{
2266
return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
src/wix/WixToolset.Core/Compiler.cs
+276
-78
@@ -2252,9 +2252,11 @@ namespace WixToolset.Core
2252
2253
if (String.IsNullOrEmpty(directoryId))
2254
{
2255
- this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Directory"));
2255
+ directoryId = "INSTALLFOLDER";
2256
+ this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
2257
}
2257
- else if (!String.IsNullOrEmpty(subdirectory))
2258
+
2259
+ if (!String.IsNullOrEmpty(subdirectory))
2260
{
2261
directoryId = this.Core.CreateDirectoryReferenceFromInlineSyntax(sourceLineNumbers, directoryId, subdirectory);
2262
}
@@ -2427,6 +2429,7 @@ namespace WixToolset.Core
2429
keyBit = ComponentKeyPathType.File;
2430
keyPossible = possibleKeyPath.Id;
2431
break;
2432
+
2433
case PossibleKeyPathType.Directory:
2434
keyBit = ComponentKeyPathType.Directory;
2435
keyPossible = String.Empty;
@@ -2581,8 +2584,8 @@ namespace WixToolset.Core
2584
/// Parses a component group element.
2585
/// </summary>
2586
/// <param name="node">Element to parse.</param>
2584
- /// <param name="parentType"></param>
2585
- /// <param name="parentId"></param>
2587
+ /// <param name="parentType">Type of complex reference parent. Will be Unknown if there is no parent.</param>
2588
+ /// <param name="parentId">Optional identifier for primary parent.</param>
2589
private void ParseComponentGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId)
2590
{
2591
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
@@ -2649,6 +2652,9 @@ namespace WixToolset.Core
2652
case "Component":
2653
this.ParseComponentElement(child, ComplexReferenceParentType.ComponentGroup, id.Id, null, CompilerConstants.IntegerNotSet, directoryId, source);
2654
break;
2655
+ case "File":
2656
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.ComponentGroup, id.Id, directoryId, source);
2657
+ break;
2658
default:
2659
this.Core.UnexpectedElement(node, child);
2660
break;
@@ -3872,6 +3878,9 @@ namespace WixToolset.Core
3878
case "Directory":
3879
this.ParseDirectoryElement(child, id.Id, diskId, fileSource);
3880
break;
3881
+ case "File":
3882
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id.Id, fileSource);
3883
+ break;
3884
case "Merge":
3885
this.ParseMergeElement(child, id.Id, diskId);
3886
break;
@@ -3984,6 +3993,9 @@ namespace WixToolset.Core
3993
case "Directory":
3994
this.ParseDirectoryElement(child, id, diskId, fileSource);
3995
break;
3996
+ case "File":
3997
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id, fileSource);
3998
+ break;
3999
case "Merge":
4000
this.ParseMergeElement(child, id, diskId);
4001
break;
@@ -4421,6 +4433,9 @@ namespace WixToolset.Core
4433
case "FeatureRef":
4434
this.ParseFeatureRefElement(child, ComplexReferenceParentType.Feature, id.Id);
4435
break;
4436
+ case "File":
4437
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Feature, id.Id, null, null);
4438
+ break;
4439
case "Level":
4440
this.ParseLevelElement(child, id.Id);
4441
break;
@@ -4561,6 +4576,9 @@ namespace WixToolset.Core
4576
case "FeatureRef":
4577
this.ParseFeatureRefElement(child, ComplexReferenceParentType.Feature, id);
4578
break;
4579
+ case "File":
4580
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Feature, id, null, null);
4581
+ break;
4582
case "MergeRef":
4583
this.ParseMergeRefElement(child, ComplexReferenceParentType.Feature, id);
4584
break;
@@ -4646,6 +4664,9 @@ namespace WixToolset.Core
4664
case "FeatureRef":
4665
this.ParseFeatureRefElement(child, ComplexReferenceParentType.FeatureGroup, id.Id);
4666
break;
4667
+ case "File":
4668
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.FeatureGroup, id.Id, null, null);
4669
+ break;
4670
case "MergeRef":
4671
this.ParseMergeRefElement(child, ComplexReferenceParentType.FeatureGroup, id.Id);
4672
break;
@@ -5029,9 +5050,8 @@ namespace WixToolset.Core
5050
}
5051
}
5052
5032
-
5053
/// <summary>
5034
- /// Parses a file element.
5054
+ /// Parses a File element's attributes.
5055
/// </summary>
5056
/// <param name="node">File element to parse.</param>
5057
/// <param name="componentId">Parent's component id.</param>
@@ -5039,10 +5059,12 @@ namespace WixToolset.Core
5059
/// <param name="diskId">Disk id inherited from parent component.</param>
5060
/// <param name="sourcePath">Default source path of parent directory.</param>
5061
/// <param name="possibleKeyPath">This will be set with the possible keyPath for the parent component.</param>
5042
- /// <param name="win64Component">true if the component is 64-bit.</param>
5043
- /// <param name="componentGuid"></param>
5062
+ /// <param name="componentGuid">Component GUID (including `*`).</param>
5063
+ /// <param name="isNakedFile">Whether the File element being parsed is outside a Component element.</param>
5064
+ /// <param name="fileSymbol">Outgoing file symbol containing parsed attributes.</param>
5065
+ /// <param name="assemblySymbol">Outgoing assembly symbol containing parsed attributes.</param>
5066
/// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
5045
- private YesNoType ParseFileElement(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out string possibleKeyPath, bool win64Component, string componentGuid)
5067
+ private YesNoType ParseFileElementAttributes(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out string possibleKeyPath, string componentGuid, bool isNakedFile, out FileSymbol fileSymbol, out AssemblySymbol assemblySymbol)
5068
{
5069
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
5070
Identifier id = null;
@@ -5083,12 +5105,25 @@ namespace WixToolset.Core
5105
var source = sourcePath; // assume we'll use the parents as the source for this file
5106
var sourceSet = false;
5107
5108
+ fileSymbol = null;
5109
+ assemblySymbol = null;
5110
+
5111
foreach (var attrib in node.Attributes())
5112
{
5113
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
5114
{
5115
switch (attrib.Name.LocalName)
5116
{
5117
+ case "Bitness":
5118
+ case "Condition":
5119
+ case "Directory":
5120
+ case "Subdirectory":
5121
+ // Naked files handle their attributes in ParseNakedFileElement.
5122
+ if (!isNakedFile)
5123
+ {
5124
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, attrib.Name.LocalName));
5125
+ }
5126
+ break;
5127
case "Id":
5128
id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
5129
break;
@@ -5329,70 +5364,6 @@ namespace WixToolset.Core
5364
}
5365
}
5366
5332
- foreach (var child in node.Elements())
5333
- {
5334
- if (CompilerCore.WixNamespace == child.Name.Namespace)
5335
- {
5336
- switch (child.Name.LocalName)
5337
- {
5338
- case "AppId":
5339
- this.ParseAppIdElement(child, componentId, YesNoType.NotSet, id.Id, null, null);
5340
- break;
5341
- case "AssemblyName":
5342
- this.ParseAssemblyName(child, componentId);
5343
- break;
5344
- case "Class":
5345
- this.ParseClassElement(child, componentId, YesNoType.NotSet, id.Id, null, null, null);
5346
- break;
5347
- case "CopyFile":
5348
- this.ParseCopyFileElement(child, componentId, id.Id);
5349
- break;
5350
- case "IgnoreRange":
5351
- this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
5352
- break;
5353
- case "ODBCDriver":
5354
- this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCDriver);
5355
- break;
5356
- case "ODBCTranslator":
5357
- this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCTranslator);
5358
- break;
5359
- case "Permission":
5360
- this.ParsePermissionElement(child, id.Id, "File");
5361
- break;
5362
- case "PermissionEx":
5363
- this.ParsePermissionExElement(child, id.Id, "File");
5364
- break;
5365
- case "ProtectRange":
5366
- this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
5367
- break;
5368
- case "Shortcut":
5369
- this.ParseShortcutElement(child, componentId, node.Name.LocalName, id.Id, keyPath);
5370
- break;
5371
- case "SymbolPath":
5372
- if (null != symbols)
5373
- {
5374
- symbols += ";" + this.ParseSymbolPathElement(child);
5375
- }
5376
- else
5377
- {
5378
- symbols = this.ParseSymbolPathElement(child);
5379
- }
5380
- break;
5381
- case "TypeLib":
5382
- this.ParseTypeLibElement(child, componentId, id.Id, win64Component);
5383
- break;
5384
- default:
5385
- this.Core.UnexpectedElement(node, child);
5386
- break;
5387
- }
5388
- }
5389
- else
5390
- {
5391
- var context = new Dictionary<string, string>() { { "FileId", id?.Id }, { "ComponentId", componentId }, { "DirectoryId", directoryId }, { "Win64", win64Component.ToString() } };
5392
- this.Core.ParseExtensionElement(node, child, context);
5393
- }
5394
- }
5395
-
5367
if (!this.Core.EncounteredError)
5368
{
5369
var patchAttributes = PatchAttributeType.None;
@@ -5427,7 +5398,7 @@ namespace WixToolset.Core
5398
attributes |= compressed.HasValue && compressed == true ? FileSymbolAttributes.Compressed : 0;
5399
attributes |= compressed.HasValue && compressed == false ? FileSymbolAttributes.Uncompressed : 0;
5400
5430
- this.Core.AddSymbol(new FileSymbol(sourceLineNumbers, id)
5401
+ fileSymbol = new FileSymbol(sourceLineNumbers, id)
5402
{
5403
ComponentRef = componentId,
5404
Name = name,
@@ -5454,11 +5425,11 @@ namespace WixToolset.Core
5425
IgnoreLengths = ignoreLengths,
5426
RetainOffsets = protectOffsets,
5427
SymbolPaths = symbols,
5457
- });
5428
+ };
5429
5430
if (AssemblyType.NotAnAssembly != assemblyType)
5431
{
5461
- this.Core.AddSymbol(new AssemblySymbol(sourceLineNumbers, id)
5432
+ assemblySymbol = new AssemblySymbol(sourceLineNumbers, id)
5433
{
5434
ComponentRef = componentId,
5435
FeatureRef = Guid.Empty.ToString("B"),
@@ -5466,7 +5437,7 @@ namespace WixToolset.Core
5437
ApplicationFileRef = assemblyApplication,
5438
Type = assemblyType,
5439
ProcessorArchitecture = procArch,
5469
- });
5440
+ };
5441
}
5442
}
5443
@@ -5485,6 +5456,227 @@ namespace WixToolset.Core
5456
return keyPath;
5457
}
5458
5459
+ /// <param name="node">File element to parse.</param>
5460
+ /// <param name="fileSymbol">The partially-parsed file symbol.</param>
5461
+ /// <param name="keyPath">Whether the file is the keypath of its component.</param>
5462
+ /// <param name="win64Component">true if the component is 64-bit.</param>
5463
+ private void ParseFileElementChildren(XElement node, FileSymbol fileSymbol, YesNoType keyPath, bool win64Component)
5464
+ {
5465
+ var directoryId = fileSymbol.DirectoryRef;
5466
+ var componentId = fileSymbol.ComponentRef;
5467
+ var id = fileSymbol.Id;
5468
+ var ignoreOffsets = fileSymbol.IgnoreOffsets;
5469
+ var ignoreLengths = fileSymbol.IgnoreLengths;
5470
+ var protectOffsets = fileSymbol.RetainOffsets;
5471
+ var protectLengths = fileSymbol.RetainLengths;
5472
+ var symbols = fileSymbol.SymbolPaths;
5473
+
5474
+ foreach (var child in node.Elements())
5475
+ {
5476
+ if (CompilerCore.WixNamespace == child.Name.Namespace)
5477
+ {
5478
+ switch (child.Name.LocalName)
5479
+ {
5480
+ case "AppId":
5481
+ this.ParseAppIdElement(child, componentId, YesNoType.NotSet, id.Id, null, null);
5482
+ break;
5483
+ case "AssemblyName":
5484
+ this.ParseAssemblyName(child, componentId);
5485
+ break;
5486
+ case "Class":
5487
+ this.ParseClassElement(child, componentId, YesNoType.NotSet, id.Id, null, null, null);
5488
+ break;
5489
+ case "CopyFile":
5490
+ this.ParseCopyFileElement(child, componentId, id.Id);
5491
+ break;
5492
+ case "IgnoreRange":
5493
+ this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
5494
+ break;
5495
+ case "ODBCDriver":
5496
+ this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCDriver);
5497
+ break;
5498
+ case "ODBCTranslator":
5499
+ this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCTranslator);
5500
+ break;
5501
+ case "Permission":
5502
+ this.ParsePermissionElement(child, id.Id, "File");
5503
+ break;
5504
+ case "PermissionEx":
5505
+ this.ParsePermissionExElement(child, id.Id, "File");
5506
+ break;
5507
+ case "ProtectRange":
5508
+ this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
5509
+ break;
5510
+ case "Shortcut":
5511
+ this.ParseShortcutElement(child, componentId, node.Name.LocalName, id.Id, keyPath);
5512
+ break;
5513
+ case "SymbolPath":
5514
+ if (null != symbols)
5515
+ {
5516
+ symbols += ";" + this.ParseSymbolPathElement(child);
5517
+ }
5518
+ else
5519
+ {
5520
+ symbols = this.ParseSymbolPathElement(child);
5521
+ }
5522
+ break;
5523
+ case "TypeLib":
5524
+ this.ParseTypeLibElement(child, componentId, id.Id, win64Component);
5525
+ break;
5526
+ default:
5527
+ this.Core.UnexpectedElement(node, child);
5528
+ break;
5529
+ }
5530
+ }
5531
+ else
5532
+ {
5533
+ var context = new Dictionary<string, string>() { { "FileId", id?.Id }, { "ComponentId", componentId }, { "DirectoryId", directoryId }, { "Win64", win64Component.ToString() } };
5534
+ this.Core.ParseExtensionElement(node, child, context);
5535
+ }
5536
+ }
5537
+
5538
+ fileSymbol.IgnoreOffsets = ignoreOffsets;
5539
+ fileSymbol.IgnoreLengths = ignoreLengths;
5540
+ fileSymbol.RetainOffsets = protectOffsets;
5541
+ fileSymbol.RetainLengths = protectLengths;
5542
+ fileSymbol.SymbolPaths = symbols;
5543
+ }
5544
+
5545
+
5546
+ /// <summary>
5547
+ /// Parses a File element.
5548
+ /// </summary>
5549
+ /// <param name="node">File element to parse.</param>
5550
+ /// <param name="componentId">Parent's component id.</param>
5551
+ /// <param name="directoryId">Ancestor's directory id.</param>
5552
+ /// <param name="diskId">Disk id inherited from parent component.</param>
5553
+ /// <param name="sourcePath">Default source path of parent directory.</param>
5554
+ /// <param name="possibleKeyPath">This will be set with the possible keyPath for the parent component.</param>
5555
+ /// <param name="win64Component">true if the component is 64-bit.</param>
5556
+ /// <param name="componentGuid">Component GUID (including `*`).</param>
5557
+ /// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
5558
+ private YesNoType ParseFileElement(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out string possibleKeyPath, bool win64Component, string componentGuid)
5559
+ {
5560
+ var keyPath = this.ParseFileElementAttributes(node, componentId, directoryId, diskId, sourcePath, out possibleKeyPath, componentGuid, isNakedFile: false, out var fileSymbol, out var assemblySymbol);
5561
+
5562
+ if (!this.Core.EncounteredError)
5563
+ {
5564
+ this.Core.AddSymbol(fileSymbol);
5565
+
5566
+ if (assemblySymbol != null)
5567
+ {
5568
+ this.Core.AddSymbol(assemblySymbol);
5569
+ }
5570
+
5571
+ this.ParseFileElementChildren(node, fileSymbol, keyPath, win64Component);
5572
+ }
5573
+
5574
+ return keyPath;
5575
+ }
5576
+
5577
+ /// <summary>
5578
+ /// Parses a file element outside a component.
5579
+ /// </summary>
5580
+ /// <param name="node">File element to parse.</param>
5581
+ /// <param name="parentType">Type of complex reference parent. Will be Unknown if there is no parent.</param>
5582
+ /// <param name="parentId">Optional identifier for primary parent.</param>
5583
+ /// <param name="directoryId">Ancestor's directory id.</param>
5584
+ /// <param name="sourcePath">Default source path of parent directory.</param>
5585
+ /// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
5586
+ private void ParseNakedFileElement(XElement node, ComplexReferenceParentType parentType, string parentId, string directoryId, string sourcePath)
5587
+ {
5588
+ var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
5589
+ var win64 = this.Context.IsCurrentPlatform64Bit;
5590
+ string condition = null;
5591
+ string subdirectory = null;
5592
+
5593
+ var keyPath = this.ParseFileElementAttributes(node, "@WixTemporaryComponentId", directoryId, diskId: CompilerConstants.IntegerNotSet, sourcePath, out var _, componentGuid: "*", isNakedFile: true, out var fileSymbol, out var assemblySymbol);
5594
+
5595
+ if (!this.Core.EncounteredError)
5596
+ {
5597
+ // Naked files have additional attributes to handle common component attributes.
5598
+ foreach (var attrib in node.Attributes())
5599
+ {
5600
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
5601
+ {
5602
+ switch (attrib.Name.LocalName)
5603
+ {
5604
+ case "Bitness":
5605
+ var bitnessValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
5606
+ switch (bitnessValue)
5607
+ {
5608
+ case "always32":
5609
+ win64 = false;
5610
+ break;
5611
+ case "always64":
5612
+ win64 = true;
5613
+ break;
5614
+ case "default":
5615
+ case "":
5616
+ break;
5617
+ default:
5618
+ this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, bitnessValue, "default", "always32", "always64"));
5619
+ break;
5620
+ }
5621
+ break;
5622
+ case "Condition":
5623
+ condition = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
5624
+ break;
5625
+ case "Directory":
5626
+ directoryId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
5627
+ this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
5628
+ break;
5629
+ case "Subdirectory":
5630
+ subdirectory = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, allowRelative: true);
5631
+ break;
5632
+ }
5633
+ }
5634
+ }
5635
+
5636
+ if (String.IsNullOrEmpty(directoryId))
5637
+ {
5638
+ directoryId = "INSTALLFOLDER";
5639
+ this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
5640
+ }
5641
+
5642
+ directoryId = this.HandleSubdirectory(sourceLineNumbers, node, directoryId, subdirectory, "Directory", "Subdirectory");
5643
+
5644
+ this.Core.AddSymbol(new ComponentSymbol(sourceLineNumbers, fileSymbol.Id)
5645
+ {
5646
+ ComponentId = "*",
5647
+ DirectoryRef = directoryId,
5648
+ Location = ComponentLocation.LocalOnly,
5649
+ Condition = condition,
5650
+ KeyPath = fileSymbol.Id.Id,
5651
+ KeyPathType = ComponentKeyPathType.File,
5652
+ DisableRegistryReflection = false,
5653
+ NeverOverwrite = false,
5654
+ Permanent = false,
5655
+ SharedDllRefCount = false,
5656
+ Shared = false,
5657
+ Transitive = false,
5658
+ UninstallWhenSuperseded = false,
5659
+ Win64 = win64,
5660
+ });
5661
+
5662
+ fileSymbol.ComponentRef = fileSymbol.Id.Id;
5663
+ this.Core.AddSymbol(fileSymbol);
5664
+
5665
+ if (assemblySymbol != null)
5666
+ {
5667
+ this.Core.AddSymbol(assemblySymbol);
5668
+ }
5669
+
5670
+ this.ParseFileElementChildren(node, fileSymbol, keyPath, win64);
5671
+
5672
+ if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that.
5673
+ {
5674
+ // If the naked file's component is defined directly under a feature, then mark the complex reference primary.
5675
+ this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.Component, fileSymbol.Id.Id, ComplexReferenceParentType.Feature == parentType);
5676
+ }
5677
+ }
5678
+ }
5679
+
5680
/// <summary>
5681
/// Parses a file search element.
5682
/// </summary>
@@ -5802,6 +5994,9 @@ namespace WixToolset.Core
5994
case "FeatureRef":
5995
this.ParseFeatureRefElement(child, ComplexReferenceParentType.Unknown, null);
5996
break;
5997
+ case "File":
5998
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, null, null);
5999
+ break;
6000
case "Icon":
6001
this.ParseIconElement(child);
6002
break;
@@ -7149,6 +7344,9 @@ namespace WixToolset.Core
7344
case "Directory":
7345
this.ParseDirectoryElement(child, id, diskId: CompilerConstants.IntegerNotSet, fileSource: String.Empty);
7346
break;
7347
+ case "File":
7348
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id, null);
7349
+ break;
7350
case "Merge":
7351
this.ParseMergeElement(child, id, diskId: CompilerConstants.IntegerNotSet);
7352
break;
@@ -7300,7 +7498,7 @@ namespace WixToolset.Core
7498
/// Parses a merge reference element.
7499
/// </summary>
7500
/// <param name="node">Element to parse.</param>
7303
- /// <param name="parentType">Parents complex reference type.</param>
7501
+ /// <param name="parentType">Parent's complex reference type.</param>
7502
/// <param name="parentId">Identifier for parent feature or feature group.</param>
7503
private void ParseMergeRefElement(XElement node, ComplexReferenceParentType parentType, string parentId)
7504
{
src/wix/WixToolset.Core/Compiler_Module.cs
+3
@@ -175,6 +175,9 @@ namespace WixToolset.Core
175
case "Exclusion":
176
this.ParseExclusionElement(child);
177
break;
178
+ case "File":
179
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Module, this.activeName, null, null);
180
+ break;
181
case "Icon":
182
this.ParseIconElement(child);
183
break;
src/wix/WixToolset.Core/Compiler_Package.cs
+3
@@ -303,6 +303,9 @@ namespace WixToolset.Core
303
case "FeatureGroupRef":
304
this.ParseFeatureGroupRefElement(child, ComplexReferenceParentType.Product, productCode);
305
break;
306
+ case "File":
307
+ this.ParseNakedFileElement(child, ComplexReferenceParentType.Product, productCode, null, null);
308
+ break;
309
case "Icon":
310
this.ParseIconElement(child);
311
break;
src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs
+4
@@ -32,6 +32,7 @@ namespace WixToolset.Core.Link
32
return;
33
}
34
35
+ // If a directory with id INSTALLFOLDER hasn't been authored, provide a default one.
36
if (!this.Find.SymbolsByName.ContainsKey(WixStandardInstallFolderReference))
37
{
38
var sourceLineNumber = new SourceLineNumber("DefaultInstallFolder");
@@ -51,6 +52,9 @@ namespace WixToolset.Core.Link
52
);
53
}
54
55
+ // If an upgrade hasn't been authored and the upgrade strategy is MajorUpgrade,
56
+ // conjure a default major upgrade with the stdlib localization string for the
57
+ // downgrade error message.
58
var symbols = this.Sections.SelectMany(section => section.Symbols);
59
var upgradeSymbols = symbols.OfType<UpgradeSymbol>();
60
if (!upgradeSymbols.Any())
src/wix/WixToolset.Core/Link/SymbolWithSection.cs
+2
@@ -4,6 +4,7 @@ namespace WixToolset.Core.Link
4
{
5
using System;
6
using System.Collections.Generic;
7
+ using System.Diagnostics;
8
using System.Linq;
9
using WixToolset.Data;
10
using WixToolset.Data.Symbols;
@@ -11,6 +12,7 @@ namespace WixToolset.Core.Link
12
/// <summary>
13
/// Symbol with section representing a single unique symbol.
14
/// </summary>
15
+ [DebuggerDisplay("{Symbol.DebuggerDisplay}")]
16
internal class SymbolWithSection
17
{
18
private List<WixSimpleReferenceSymbol> directReferences;
src/wix/test/WixToolsetTest.CoreIntegration/ComponentFixture.cs
-29
@@ -41,34 +41,5 @@ namespace WixToolsetTest.CoreIntegration
41
}, errors.Select(e => e.Id).ToArray());
42
}
43
}
44
-
45
- [Fact]
46
- public void CannotBuildMissingDirectoryAttributeWithSubdirectory()
47
- {
48
- var folder = TestData.Get(@"TestData");
49
-
50
- using (var fs = new DisposableFileSystem())
51
- {
52
- var baseFolder = fs.GetFolder();
53
- var intermediateFolder = Path.Combine(baseFolder, "obj");
54
- var msiPath = Path.Combine(baseFolder, "bin", "test.msi");
55
-
56
- var result = WixRunner.Execute(new[]
57
- {
58
- "build",
59
- Path.Combine(folder, "Component", "MissingDirectoryWithSubdirectory.wxs"),
60
- Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
61
- "-bindpath", Path.Combine(folder, "SingleFile", "data"),
62
- "-intermediateFolder", intermediateFolder,
63
- "-o", msiPath
64
- });
65
-
66
- var errors = result.Messages.Select(m => m.ToString()).ToArray();
67
- WixAssert.CompareLineByLine(new[]
68
- {
69
- "The Component/@Directory attribute was not found; it is required."
70
- }, errors);
71
- }
72
- }
44
}
45
}
src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs
new
+247
@@ -0,0 +1,247 @@
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.Data;
6
+ using System.IO;
7
+ using System.Linq;
8
+ using WixInternal.Core.TestPackage;
9
+ using WixInternal.TestSupport;
10
+ using WixToolset.Data.WindowsInstaller;
11
+ using Xunit;
12
+
13
+ public class NakedFileFixture
14
+ {
15
+ [Fact]
16
+ public void CanBuildNakedFilesInComponentGroup()
17
+ {
18
+ var rows = BuildAndQueryComponentAndFileTables("ComponentGroup.wxs");
19
+
20
+ AssertFileComponentIds(2, rows);
21
+ }
22
+
23
+ [Fact]
24
+ public void CanBuildNakedFilesInFeature()
25
+ {
26
+ var rows = BuildAndQueryComponentAndFileTables("Feature.wxs");
27
+
28
+ AssertFileComponentIds(2, rows);
29
+ }
30
+
31
+ [Fact]
32
+ public void CanBuildNakedFilesInDirectory()
33
+ {
34
+ var rows = BuildAndQueryComponentAndFileTables("Directory.wxs");
35
+
36
+ AssertFileComponentIds(2, rows);
37
+ }
38
+
39
+ [Fact]
40
+ public void CanBuildNakedFilesInDirectoryRef()
41
+ {
42
+ var rows = BuildAndQueryComponentAndFileTables("DirectoryRef.wxs");
43
+
44
+ AssertFileComponentIds(2, rows);
45
+ }
46
+
47
+ [Fact]
48
+ public void CanBuildNakedFilesInFeatureRef()
49
+ {
50
+ var rows = BuildAndQueryComponentAndFileTables("FeatureRef.wxs");
51
+
52
+ AssertFileComponentIds(2, rows);
53
+ }
54
+
55
+ [Fact]
56
+ public void CanBuildNakedFilesInFeatureGroup()
57
+ {
58
+ var rows = BuildAndQueryComponentAndFileTables("FeatureGroup.wxs");
59
+
60
+ AssertFileComponentIds(2, rows);
61
+ }
62
+
63
+ [Fact]
64
+ public void CanBuildNakedFilesInFragments()
65
+ {
66
+ var rows = BuildAndQueryComponentAndFileTables("Fragment.wxs");
67
+
68
+ AssertFileComponentIds(2, rows);
69
+ }
70
+
71
+ [Fact]
72
+ public void CanBuildNakedFilesInStandardDirectory()
73
+ {
74
+ var rows = BuildAndQueryComponentAndFileTables("StandardDirectory.wxs");
75
+
76
+ AssertFileComponentIds(2, rows);
77
+ }
78
+
79
+ [Fact]
80
+ public void CanBuildNakedFilesInModule()
81
+ {
82
+ var rows = BuildAndQueryComponentAndFileTables("Module.wxs", isPackage: false);
83
+
84
+ AssertFileComponentIds(2, rows);
85
+ }
86
+
87
+ [Fact]
88
+ public void CanBuildNakedFilesWithConditions()
89
+ {
90
+ var rows = BuildAndQueryComponentAndFileTables("Condition.wxs");
91
+ var componentRows = rows.Where(row => row.StartsWith("Component:")).ToArray();
92
+
93
+ // Coincidentally, the files' ids are the same as the component conditions.
94
+ foreach (var componentRow in componentRows)
95
+ {
96
+ var columns = componentRow.Split(':', '\t');
97
+ Assert.Equal(columns[1], columns[5]);
98
+ }
99
+ }
100
+
101
+ [Fact]
102
+ public void CanBuildNakedFilesUnderPackage()
103
+ {
104
+ var rows = BuildAndQueryComponentAndFileTables("Package.wxs");
105
+ AssertFileComponentIds(4, rows);
106
+ }
107
+
108
+ [Fact]
109
+ public void CanBuildNakedFilesUnderPackageWithDefaultInstallFolder()
110
+ {
111
+ var rows = BuildAndQueryComponentAndFileTables("PackageWithDefaultInstallFolder.wxs");
112
+ AssertFileComponentIds(4, rows);
113
+ }
114
+
115
+ [Fact]
116
+ public void NakedFilesUnderPackageWithAuthoredFeatureAreOrphaned()
117
+ {
118
+ var messages = BuildAndQueryComponentAndFileTables("PackageWithoutDefaultFeature.wxs", isPackage: true, 267);
119
+ Assert.Equal(new[]
120
+ {
121
+ "267",
122
+ "267",
123
+ }, messages);
124
+ }
125
+
126
+ [Fact]
127
+ public void IllegalAttributesWhenNonNakedFailTheBuild()
128
+ {
129
+ var messages = BuildAndQueryComponentAndFileTables("BadAttributes.wxs", isPackage: true, 62);
130
+ Assert.Equal(new[]
131
+ {
132
+ "62",
133
+ "62",
134
+ "62",
135
+ "62",
136
+ }, messages);
137
+ }
138
+
139
+ [Fact]
140
+ public void CanBuildNakedFileFromWixlibComponentGroup()
141
+ {
142
+ var rows = BuildPackageWithWixlib("WixlibComponentGroup.wxs", "WixlibComponentGroupPackage.wxs");
143
+
144
+ AssertFileComponentIds(2, rows);
145
+ }
146
+
147
+ private static string[] BuildPackageWithWixlib(string wixlibSourcePath, string msiSourcePath)
148
+ {
149
+ var folder = TestData.Get("TestData", "NakedFile");
150
+
151
+ using (var fs = new DisposableFileSystem())
152
+ {
153
+ var baseFolder = fs.GetFolder();
154
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
155
+ var binFolder = Path.Combine(baseFolder, "bin");
156
+ var wixlibPath = Path.Combine(binFolder, Path.ChangeExtension(wixlibSourcePath, ".wixlib"));
157
+
158
+ var result = WixRunner.Execute(new[]
159
+ {
160
+ "build",
161
+ Path.Combine(folder, wixlibSourcePath),
162
+ "-intermediateFolder", intermediateFolder,
163
+ "-bindpath", folder,
164
+ "-o", wixlibPath,
165
+ });
166
+
167
+ result.AssertSuccess();
168
+
169
+ var msiPath = Path.Combine(binFolder, "test.msi");
170
+
171
+ result = WixRunner.Execute(new[]
172
+ {
173
+ "build",
174
+ Path.Combine(folder, msiSourcePath),
175
+ wixlibPath,
176
+ "-intermediateFolder", intermediateFolder,
177
+ "-bindpath", folder,
178
+ "-o", msiPath,
179
+ });
180
+ result.AssertSuccess();
181
+
182
+ return Query.QueryDatabase(msiPath, new[] { "Component", "File" })
183
+ .OrderBy(s => s)
184
+ .ToArray();
185
+ }
186
+ }
187
+
188
+ private static string[] BuildAndQueryComponentAndFileTables(string file, bool isPackage = true, int? exitCode = null)
189
+ {
190
+ var folder = TestData.Get("TestData", "NakedFile");
191
+
192
+ using (var fs = new DisposableFileSystem())
193
+ {
194
+ var baseFolder = fs.GetFolder();
195
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
196
+ var binFolder = Path.Combine(baseFolder, "bin");
197
+ var msiPath = Path.Combine(binFolder, isPackage ? "test.msi" : "test.msm");
198
+
199
+ var result = WixRunner.Execute(new[]
200
+ {
201
+ "build",
202
+ Path.Combine(folder, file),
203
+ "-intermediateFolder", intermediateFolder,
204
+ "-bindpath", folder,
205
+ "-o", msiPath,
206
+ });
207
+
208
+ if (exitCode.HasValue)
209
+ {
210
+ Assert.Equal(exitCode.Value, result.ExitCode);
211
+
212
+ return result.Messages.Select(m => m.Id.ToString()).ToArray();
213
+ }
214
+ else
215
+ {
216
+ result.AssertSuccess();
217
+
218
+ return Query.QueryDatabase(msiPath, new[] { "Component", "File" })
219
+ .OrderBy(s => s)
220
+ .ToArray();
221
+ }
222
+ }
223
+ }
224
+
225
+ private static void AssertFileComponentIds(int fileCount, string[] rows)
226
+ {
227
+ var componentRows = rows.Where(row => row.StartsWith("Component:")).ToArray();
228
+ var fileRows = rows.Where(row => row.StartsWith("File:")).ToArray();
229
+
230
+ Assert.Equal(fileCount, componentRows.Length);
231
+ Assert.Equal(componentRows.Length, fileRows.Length);
232
+
233
+ // Component id == Component keypath == File id
234
+ foreach (var componentRow in componentRows)
235
+ {
236
+ var columns = componentRow.Split(':', '\t');
237
+ Assert.Equal(columns[1], columns[6]);
238
+ }
239
+
240
+ foreach (var fileRow in fileRows)
241
+ {
242
+ var columns = fileRow.Split(':', '\t');
243
+ Assert.Equal(columns[1], columns[2]);
244
+ }
245
+ }
246
+ }
247
+}
src/wix/test/WixToolsetTest.CoreIntegration/TestData/Component/MissingDirectoryWithSubdirectory.wxs
deleted
-10
@@ -1,10 +0,0 @@
1
-<?xml version="1.0" encoding="utf-8"?>
2
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3
- <Fragment>
4
- <ComponentGroup Id="ProductComponents">
5
- <Component Subdirectory="fails\without\Directory\attribute">
6
- <File Source="test.txt" />
7
- </Component>
8
- </ComponentGroup>
9
- </Fragment>
10
-</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/BadAttributes.wxs
new
+11
@@ -0,0 +1,11 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <Feature Id="ProductFeature">
6
+ <Component Directory="ProgramFilesFolder" Subdirectory="MsiPackage">
7
+ <File Source="test.txt" Bitness="always64" Condition="BLAHBLAHBLAH" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" />
8
+ </Component>
9
+ </Feature>
10
+ </Package>
11
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/ComponentGroup.wxs
new
+14
@@ -0,0 +1,14 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <Feature Id="ProductFeature">
6
+ <ComponentGroupRef Id="Files" />
7
+ </Feature>
8
+
9
+ <ComponentGroup Id="Files" Directory="ProgramFilesFolder" Subdirectory="MsiPackage">
10
+ <File Source="test.txt" />
11
+ <File Source="test.txt" Name="test2.txt" />
12
+ </ComponentGroup>
13
+ </Package>
14
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Condition.wxs
new
+10
@@ -0,0 +1,10 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <Feature Id="ProductFeature">
6
+ <File Id="FILE1" Condition="FILE1" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
7
+ <File Id="FILE2" Condition="FILE2" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
8
+ </Feature>
9
+ </Package>
10
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Directory.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <StandardDirectory Id="ProgramFilesFolder">
6
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage">
7
+ <!-- Relies on default-feature feature to include naked files in package. -->
8
+ <File Id="test.txt" Source="test.txt" />
9
+ <File Id="test2.txt" Source="test.txt" Name="test2.txt" />
10
+ </Directory>
11
+ </StandardDirectory>
12
+ </Package>
13
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/DirectoryRef.wxs
new
+17
@@ -0,0 +1,17 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <DirectoryRef Id="INSTALLFOLDER">
6
+ <!-- Relies on default-feature feature to include naked files in package. -->
7
+ <File Id="test.txt" Source="test.txt" />
8
+ <File Id="test2.txt" Source="test.txt" Name="test2.txt" />
9
+ </DirectoryRef>
10
+ </Package>
11
+
12
+ <Fragment>
13
+ <StandardDirectory Id="ProgramFilesFolder">
14
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
15
+ </StandardDirectory>
16
+ </Fragment>
17
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Feature.wxs
new
+10
@@ -0,0 +1,10 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <Feature Id="ProductFeature">
6
+ <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
7
+ <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
8
+ </Feature>
9
+ </Package>
10
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/FeatureGroup.wxs
new
+22
@@ -0,0 +1,22 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <Feature Id="ProductFeature">
6
+ <FeatureGroupRef Id="ProductFeatureGroup" />
7
+ </Feature>
8
+ </Package>
9
+
10
+ <Fragment>
11
+ <StandardDirectory Id="ProgramFilesFolder">
12
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
13
+ </StandardDirectory>
14
+ </Fragment>
15
+
16
+ <Fragment>
17
+ <FeatureGroup Id="ProductFeatureGroup">
18
+ <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
19
+ <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
20
+ </FeatureGroup>
21
+ </Fragment>
22
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/FeatureRef.wxs
new
+20
@@ -0,0 +1,20 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <FeatureRef Id="ProductFeature">
6
+ <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
7
+ <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
8
+ </FeatureRef>
9
+ </Package>
10
+
11
+ <Fragment>
12
+ <StandardDirectory Id="ProgramFilesFolder">
13
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
14
+ </StandardDirectory>
15
+ </Fragment>
16
+
17
+ <Fragment>
18
+ <Feature Id="ProductFeature" />
19
+ </Fragment>
20
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Fragment.wxs
new
+24
@@ -0,0 +1,24 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <FeatureGroupRef Id="FeatureGroup1" />
6
+ <PropertyRef Id="Property2" />
7
+ </Package>
8
+
9
+ <Fragment>
10
+ <StandardDirectory Id="ProgramFilesFolder">
11
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
12
+ </StandardDirectory>
13
+ </Fragment>
14
+
15
+ <Fragment>
16
+ <FeatureGroup Id="FeatureGroup1" />
17
+ <File Id="test.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
18
+ </Fragment>
19
+
20
+ <Fragment>
21
+ <Property Id="Property2" Hidden="yes" />
22
+ <File Id="test2.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
23
+ </Fragment>
24
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Module.wxs
new
+6
@@ -0,0 +1,6 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Module Id="MergeModule" Guid="e535b765-1019-4a4f-b3ea-ae28870e6d73" Language="1033" Version="1.0.0.0">
3
+ <File Id="FILE1" Condition="FILE1" Directory="ProgramFilesFolder" Subdirectory="MergeModule" Source="test.txt" />
4
+ <File Id="FILE2" Condition="FILE2" Directory="ProgramFilesFolder" Subdirectory="MergeModule" Source="test.txt" Name="test2.txt" />
5
+ </Module>
6
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Package.wxs
new
+10
@@ -0,0 +1,10 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <File Directory="INSTALLFOLDER" Source="test.txt" />
6
+ <File Directory="INSTALLFOLDER" Source="test.txt" Name="test2.txt" />
7
+ <File Directory="INSTALLFOLDER" Source="test.txt" Name="test3.txt" />
8
+ <File Directory="INSTALLFOLDER" Source="test.txt" Name="test4.txt" />
9
+ </Package>
10
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/PackageWithDefaultInstallFolder.wxs
new
+10
@@ -0,0 +1,10 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <File Source="test.txt" />
6
+ <File Source="test.txt" Name="test2.txt" />
7
+ <File Source="test.txt" Name="test3.txt" />
8
+ <File Source="test.txt" Name="test4.txt" />
9
+ </Package>
10
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/PackageWithoutDefaultFeature.wxs
new
+17
@@ -0,0 +1,17 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <File Source="test.txt" Name="test3.txt" />
6
+ <File Source="test.txt" Name="test4.txt" />
7
+
8
+ <Feature Id="ProductFeature">
9
+ <ComponentGroupRef Id="Files" />
10
+ </Feature>
11
+
12
+ <ComponentGroup Id="Files" Directory="ProgramFilesFolder" Subdirectory="MsiPackage">
13
+ <File Source="test.txt" />
14
+ <File Source="test.txt" Name="test2.txt" />
15
+ </ComponentGroup>
16
+ </Package>
17
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/StandardDirectory.wxs
new
+11
@@ -0,0 +1,11 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4
+
5
+ <StandardDirectory Id="ProgramFilesFolder">
6
+ <!-- Relies on default-feature feature to include naked files in package. -->
7
+ <File Id="test.txt" Source="test.txt" />
8
+ <File Id="test2.txt" Source="test.txt" Name="test2.txt" />
9
+ </StandardDirectory>
10
+ </Package>
11
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/WixlibComponentGroup.wxs
new
+8
@@ -0,0 +1,8 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Fragment>
3
+ <ComponentGroup Id="WixlibFiles">
4
+ <File Id="test.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
5
+ <File Id="test2.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
6
+ </ComponentGroup>
7
+ </Fragment>
8
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/WixlibComponentGroupPackage.wxs
new
+5
@@ -0,0 +1,5 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <ComponentGroupRef Id="WixlibFiles" />
4
+ </Package>
5
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/test.txt
new
+1
@@ -0,0 +1 @@
1
+This is test.txt.
src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/PackageComponents.wxs
+2
-3
@@ -2,9 +2,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>
5
+ <File Source="test.txt" />
6
+
7
<Component Id="Shared.dll" Shared="yes">
8
<File Name="Shared.dll" Source="test.txt" />
9
</Component>