Integrate tools from Core project

This commit is contained in:
Rob Mensching 2018-07-21 07:36:34 -07:00
Родитель 6fc54af07b
Коммит 306f1d0c52
71 изменённых файлов: 7975 добавлений и 0 удалений

49
Tools.sln Normal file
Просмотреть файл

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.BuildTasks", "src\test\WixToolsetTest.BuildTasks\WixToolsetTest.BuildTasks.csproj", "{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "wix", "src\wix\wix.csproj", "{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.BuildTasks", "src\WixToolset.BuildTasks\WixToolset.BuildTasks.csproj", "{65141CE1-0BDD-41EF-8043-35B96C423CB6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-wix", "src\dotnet-wix\dotnet-wix.csproj", "{938BCA04-610B-4B99-9CB7-02BF7397A972}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.MSBuild", "src\WixToolset.MSBuild\WixToolset.MSBuild.csproj", "{0DF5D4CF-8457-469D-8288-13775E984F70}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Release|Any CPU.Build.0 = Release|Any CPU
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Release|Any CPU.Build.0 = Release|Any CPU
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Release|Any CPU.Build.0 = Release|Any CPU
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Debug|Any CPU.Build.0 = Debug|Any CPU
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Release|Any CPU.ActiveCfg = Release|Any CPU
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Release|Any CPU.Build.0 = Release|Any CPU
{0DF5D4CF-8457-469D-8288-13775E984F70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DF5D4CF-8457-469D-8288-13775E984F70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DF5D4CF-8457-469D-8288-13775E984F70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DF5D4CF-8457-469D-8288-13775E984F70}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AEB88B8C-8C84-4E97-9886-30CBDD32B34B}
EndGlobalSection
EndGlobal

21
appveyor.cmd Normal file
Просмотреть файл

@ -0,0 +1,21 @@
@setlocal
@pushd %~dp0
@set _P=%~dp0build\Release\publish
@rem Disable this test until publishing of native assets is worked out
@rem dotnet build -c Release src\test\WixToolsetTest.BuildTasks
dotnet publish -c Release -o %_P%\dotnet-wix\ -f netcoreapp2.1 src\wix
dotnet publish -c Release -o %_P%\WixToolset.MSBuild\net461\ -f net461 src\WixToolset.BuildTasks
dotnet publish -c Release -o %_P%\WixToolset.MSBuild\netcoreapp2.1\ -f netcoreapp2.1 src\WixToolset.BuildTasks
@rem dotnet publish -c Release -o %_P%\netcoreapp2.1 -r win-x86 src\wix
@rem dotnet publish -c Release -o %_P%\net461 -r win-x86 src\light
@rem dotnet publish -c Release -o %_P%\net461 -r win-x86 src\WixToolset.BuildTasks
dotnet pack -c Release src\dotnet-wix
dotnet pack -c Release src\WixToolset.MSBuild
@rem dotnet pack -c Release src\WixToolset.Core.InternalPackage
@popd
@endlocal

29
appveyor.yml Normal file
Просмотреть файл

@ -0,0 +1,29 @@
image: Visual Studio 2017
version: 0.0.0.{build}
configuration: Release
environment:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
NUGET_XMLDOC_MODE: skip
build_script:
- appveyor.cmd
pull_requests:
do_not_increment_build_number: true
nuget:
disable_publish_on_pr: true
skip_tags: true
artifacts:
- path: build\Release\**\*.nupkg
name: nuget
notifications:
- provider: Slack
incoming_webhook:
secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA=

13
nuget.config Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" />
<add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" />
<add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" />
<add key="wixtoolset-dtf" value="https://ci.appveyor.com/nuget/wixtoolset-dtf" />
<add key="wixtoolset-extensibility" value="https://ci.appveyor.com/nuget/wixtoolset-extensibility" />
<add key="wixbuildtools" value="https://ci.appveyor.com/nuget/wixbuildtools" />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>

22
src/Directory.Build.props Normal file
Просмотреть файл

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)..\build\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
<BaseOutputPath>$(MSBuildThisFileDirectory)..\build\$(Configuration)\</BaseOutputPath>
<OutputPath>$(BaseOutputPath)</OutputPath>
<Authors>WiX Toolset Team</Authors>
<Company>WiX Toolset</Company>
<Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright>
<Product>WiX Toolset</Product>
</PropertyGroup>
<PropertyGroup>
<WixToolsetRootFolder>$(MSBuildThisFileDirectory)..\..\</WixToolsetRootFolder>
</PropertyGroup>
<Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " />
</Project>

Просмотреть файл

@ -0,0 +1,7 @@
// 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.
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,26 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Globalization;
class BuildException : Exception
{
public BuildException()
{
}
public BuildException(string message) : base(message)
{
}
public BuildException(string message, Exception innerException) : base(message, innerException)
{
}
public BuildException(string format, params string[] args) : this(String.Format(CultureInfo.CurrentCulture, format, args))
{
}
}
}

Просмотреть файл

@ -0,0 +1,199 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task to run the WiX compiler.
/// </summary>
public sealed class CandleOld : WixToolTask
{
private const string CandleToolName = "candle.exe";
private string[] defineConstants;
private ITaskItem[] extensions;
private string[] includeSearchPaths;
private ITaskItem outputFile;
private bool pedantic;
private string installerPlatform;
private string preprocessToFile;
private bool preprocessToStdOut;
private ITaskItem[] sourceFiles;
private string extensionDirectory;
private string[] referencePaths;
public string[] DefineConstants
{
get { return this.defineConstants; }
set { this.defineConstants = value; }
}
public ITaskItem[] Extensions
{
get { return this.extensions; }
set { this.extensions = value; }
}
public string[] IncludeSearchPaths
{
get { return this.includeSearchPaths; }
set { this.includeSearchPaths = value; }
}
public string InstallerPlatform
{
get { return this.installerPlatform; }
set { this.installerPlatform = value; }
}
[Output]
[Required]
public ITaskItem OutputFile
{
get { return this.outputFile; }
set { this.outputFile = value; }
}
public bool Pedantic
{
get { return this.pedantic; }
set { this.pedantic = value; }
}
public string PreprocessToFile
{
get { return this.preprocessToFile; }
set { this.preprocessToFile = value; }
}
public bool PreprocessToStdOut
{
get { return this.preprocessToStdOut; }
set { this.preprocessToStdOut = value; }
}
[Required]
public ITaskItem[] SourceFiles
{
get { return this.sourceFiles; }
set { this.sourceFiles = value; }
}
public string ExtensionDirectory
{
get { return this.extensionDirectory; }
set { this.extensionDirectory = value; }
}
public string[] ReferencePaths
{
get { return this.referencePaths; }
set { this.referencePaths = value; }
}
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of candle.exe.</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return CandleToolName; }
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply candle.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return CandleToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), CandleToolName);
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
base.BuildCommandLine(commandLineBuilder);
commandLineBuilder.AppendIfTrue("-p", this.PreprocessToStdOut);
commandLineBuilder.AppendSwitchIfNotNull("-p", this.PreprocessToFile);
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendArrayIfNotNull("-d", this.DefineConstants);
commandLineBuilder.AppendArrayIfNotNull("-I", this.IncludeSearchPaths);
commandLineBuilder.AppendIfTrue("-pedantic", this.Pedantic);
commandLineBuilder.AppendSwitchIfNotNull("-arch ", this.InstallerPlatform);
commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.referencePaths);
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
// Support per-source-file output by looking at the SourceFiles items to
// see if there is any "CandleOutput" metadata. If there is, we do our own
// appending, otherwise we fall back to the built-in "append file names" code.
// Note also that the wix.targets "Compile" target does *not* automagically
// fix the "@(CompileObjOutput)" list to include these new output names.
// If you really want to use this, you're going to have to clone the target
// in your own .targets file and create the output list yourself.
bool usePerSourceOutput = false;
if (this.SourceFiles != null)
{
foreach (ITaskItem item in this.SourceFiles)
{
if (!String.IsNullOrEmpty(item.GetMetadata("CandleOutput")))
{
usePerSourceOutput = true;
break;
}
}
}
if (usePerSourceOutput)
{
string[] newSourceNames = new string[this.SourceFiles.Length];
for (int iSource = 0; iSource < this.SourceFiles.Length; ++iSource)
{
ITaskItem item = this.SourceFiles[iSource];
if (null == item)
{
newSourceNames[iSource] = null;
}
else
{
string output = item.GetMetadata("CandleOutput");
if (!String.IsNullOrEmpty(output))
{
newSourceNames[iSource] = String.Concat(item.ItemSpec, ";", output);
}
else
{
newSourceNames[iSource] = item.ItemSpec;
}
}
}
commandLineBuilder.AppendFileNamesIfNotNull(newSourceNames, " ");
}
else
{
commandLineBuilder.AppendFileNamesIfNotNull(this.SourceFiles, " ");
}
}
}
}

Просмотреть файл

@ -0,0 +1,41 @@
// 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.
namespace WixToolset
{
using System;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
/// <summary>
/// Common WixTasks utility methods and types.
/// </summary>
internal static class Common
{
/// <summary>Metadata key name to turn off harvesting of project references.</summary>
public const string DoNotHarvest = "DoNotHarvest";
private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled);
private static readonly Regex IllegalIdentifierCharacters = new Regex(@"[^A-Za-z0-9_\.]|\.{2,}", RegexOptions.Compiled); // non 'words' and assorted valid characters
/// <summary>
/// Return an identifier based on passed file/directory name
/// </summary>
/// <param name="name">File/directory name to generate identifer from</param>
/// <returns>A version of the name that is a legal identifier.</returns>
/// <remarks>This is duplicated from WiX's Common class.</remarks>
internal static string GetIdentifierFromName(string name)
{
string result = IllegalIdentifierCharacters.Replace(name, "_"); // replace illegal characters with "_".
// MSI identifiers must begin with an alphabetic character or an
// underscore. Prefix all other values with an underscore.
if (AddPrefix.IsMatch(name))
{
result = String.Concat("_", result);
}
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// This task assigns Culture metadata to files based on the value of the Culture attribute on the
/// WixLocalization element inside the file.
/// </summary>
public class ConvertReferences : Task
{
private string projectOutputGroups;
private ITaskItem[] projectReferences;
private ITaskItem[] harvestItems;
/// <summary>
/// The total list of cabs in this database
/// </summary>
[Output]
public ITaskItem[] HarvestItems
{
get { return this.harvestItems; }
}
/// <summary>
/// The project output groups to harvest.
/// </summary>
[Required]
public string ProjectOutputGroups
{
get { return this.projectOutputGroups; }
set { this.projectOutputGroups = value; }
}
/// <summary>
/// All the project references in the project.
/// </summary>
[Required]
public ITaskItem[] ProjectReferences
{
get { return this.projectReferences; }
set { this.projectReferences = value; }
}
/// <summary>
/// Gets a complete list of external cabs referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
List<ITaskItem> newItems = new List<ITaskItem>();
foreach(ITaskItem item in this.ProjectReferences)
{
Dictionary<string, string> newItemMetadeta = new Dictionary<string, string>();
if (!String.IsNullOrEmpty(item.GetMetadata(Common.DoNotHarvest)))
{
continue;
}
string refTargetDir = item.GetMetadata("RefTargetDir");
if (!String.IsNullOrEmpty(refTargetDir))
{
newItemMetadeta.Add("DirectoryIds", refTargetDir);
}
string refName = item.GetMetadata("Name");
if (!String.IsNullOrEmpty(refName))
{
newItemMetadeta.Add("ProjectName", refName);
}
newItemMetadeta.Add("ProjectOutputGroups", this.ProjectOutputGroups);
ITaskItem newItem = new TaskItem(item.ItemSpec, newItemMetadeta);
newItems.Add(newItem);
}
this.harvestItems = newItems.ToArray();
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// This task assigns Culture metadata to files based on the value of the Culture attribute on the
/// WixLocalization element inside the file.
/// </summary>
public class CreateItemAvoidingInference : Task
{
private string inputProperties;
private ITaskItem[] outputItems;
/// <summary>
/// The output items.
/// </summary>
[Output]
public ITaskItem[] OuputItems
{
get { return this.outputItems; }
}
/// <summary>
/// The properties to converty to items.
/// </summary>
[Required]
public string InputProperties
{
get { return this.inputProperties; }
set { this.inputProperties = value; }
}
/// <summary>
/// Gets a complete list of external cabs referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
List<ITaskItem> newItems = new List<ITaskItem>();
foreach (string property in this.inputProperties.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
newItems.Add(new TaskItem(property));
}
this.outputItems = newItems.ToArray();
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,271 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task to create a list of preprocessor defines to be passed to candle from the
/// list of referenced projects.
/// </summary>
public sealed class CreateProjectReferenceDefineConstants : Task
{
private ITaskItem[] defineConstants;
private ITaskItem[] projectConfigurations;
private ITaskItem[] projectReferencePaths;
[Output]
public ITaskItem[] DefineConstants
{
get { return this.defineConstants; }
}
[Required]
public ITaskItem[] ProjectReferencePaths
{
get { return this.projectReferencePaths; }
set { this.projectReferencePaths = value; }
}
public ITaskItem[] ProjectConfigurations
{
get { return this.projectConfigurations; }
set { this.projectConfigurations = value; }
}
public override bool Execute()
{
List<ITaskItem> outputItems = new List<ITaskItem>();
Dictionary<string, string> defineConstants = new Dictionary<string, string>();
for (int i = 0; i < this.ProjectReferencePaths.Length; i++)
{
ITaskItem item = this.ProjectReferencePaths[i];
string configuration = item.GetMetadata("Configuration");
string fullConfiguration = item.GetMetadata("FullConfiguration");
string platform = item.GetMetadata("Platform");
string projectPath = CreateProjectReferenceDefineConstants.GetProjectPath(this.ProjectReferencePaths, i);
string projectDir = Path.GetDirectoryName(projectPath) + Path.DirectorySeparatorChar;
string projectExt = Path.GetExtension(projectPath);
string projectFileName = Path.GetFileName(projectPath);
string projectName = Path.GetFileNameWithoutExtension(projectPath);
string referenceName = CreateProjectReferenceDefineConstants.GetReferenceName(item, projectName);
string targetPath = item.GetMetadata("FullPath");
string targetDir = Path.GetDirectoryName(targetPath) + Path.DirectorySeparatorChar;
string targetExt = Path.GetExtension(targetPath);
string targetFileName = Path.GetFileName(targetPath);
string targetName = Path.GetFileNameWithoutExtension(targetPath);
// If there is no configuration metadata on the project reference task item,
// check for any additional configuration data provided in the optional task property.
if (String.IsNullOrEmpty(fullConfiguration))
{
fullConfiguration = this.FindProjectConfiguration(projectName);
if (!String.IsNullOrEmpty(fullConfiguration))
{
string[] typeAndPlatform = fullConfiguration.Split('|');
configuration = typeAndPlatform[0];
platform = (typeAndPlatform.Length > 1 ? typeAndPlatform[1] : String.Empty);
}
}
// write out the platform/configuration defines
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.Configuration", referenceName)] = configuration;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.FullConfiguration", referenceName)] = fullConfiguration;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.Platform", referenceName)] = platform;
// write out the ProjectX defines
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectDir", referenceName)] = projectDir;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectExt", referenceName)] = projectExt;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectFileName", referenceName)] = projectFileName;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectName", referenceName)] = projectName;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectPath", referenceName)] = projectPath;
// write out the TargetX defines
string targetDirDefine = String.Format(CultureInfo.InvariantCulture, "{0}.TargetDir", referenceName);
if (defineConstants.ContainsKey(targetDirDefine))
{
//if target dir was already defined, redefine it as the common root shared by multiple references from the same project
string commonDir = FindCommonRoot(targetDir, defineConstants[targetDirDefine]);
if (!String.IsNullOrEmpty(commonDir))
{
targetDir = commonDir;
}
}
defineConstants[targetDirDefine] = CreateProjectReferenceDefineConstants.EnsureEndsWithBackslash(targetDir);
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.TargetExt", referenceName)] = targetExt;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.TargetFileName", referenceName)] = targetFileName;
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.TargetName", referenceName)] = targetName;
//if target path was already defined, append to it creating a list of multiple references from the same project
string targetPathDefine = String.Format(CultureInfo.InvariantCulture, "{0}.TargetPath", referenceName);
if (defineConstants.ContainsKey(targetPathDefine))
{
string oldTargetPath = defineConstants[targetPathDefine];
if (!targetPath.Equals(oldTargetPath, StringComparison.OrdinalIgnoreCase))
{
defineConstants[targetPathDefine] += ";" + targetPath;
}
//If there was only one targetpath we need to create its culture specific define
if (!oldTargetPath.Contains(";"))
{
string oldSubFolder = FindSubfolder(oldTargetPath, targetDir, targetFileName);
if (!String.IsNullOrEmpty(oldSubFolder))
{
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.{1}.TargetPath", referenceName, oldSubFolder.Replace('\\', '_'))] = oldTargetPath;
}
}
// Create a culture specific define
string subFolder = FindSubfolder(targetPath, targetDir, targetFileName);
if (!String.IsNullOrEmpty(subFolder))
{
defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.{1}.TargetPath", referenceName, subFolder.Replace('\\', '_'))] = targetPath;
}
}
else
{
defineConstants[targetPathDefine] = targetPath;
}
}
foreach (KeyValuePair<string, string> define in defineConstants)
{
outputItems.Add(new TaskItem(String.Format(CultureInfo.InvariantCulture, "{0}={1}", define.Key, define.Value)));
}
this.defineConstants = outputItems.ToArray();
return true;
}
public static string GetProjectPath(ITaskItem[] projectReferencePaths, int i)
{
return projectReferencePaths[i].GetMetadata("MSBuildSourceProjectFile");
}
public static string GetReferenceName(ITaskItem item, string projectName)
{
string referenceName = item.GetMetadata("Name");
if (String.IsNullOrEmpty(referenceName))
{
referenceName = projectName;
}
// We cannot have an equals sign in the variable name because it
// messes with the preprocessor definitions on the command line.
referenceName = referenceName.Replace('=', '_');
// We cannot have a double quote on the command line because it
// there is no way to escape it on the command line.
referenceName = referenceName.Replace('\"', '_');
// We cannot have parens in the variable name because the WiX
// preprocessor will not be able to parse it.
referenceName = referenceName.Replace('(', '_');
referenceName = referenceName.Replace(')', '_');
return referenceName;
}
/// <summary>
/// Look through the configuration data in the ProjectConfigurations property
/// to find the configuration for a project, if available.
/// </summary>
/// <param name="projectName">Name of the project that is being searched for.</param>
/// <returns>Full configuration spec, for example "Release|Win32".</returns>
private string FindProjectConfiguration(string projectName)
{
string configuration = String.Empty;
if (this.ProjectConfigurations != null)
{
foreach (ITaskItem configItem in this.ProjectConfigurations)
{
string configProject = configItem.ItemSpec;
if (configProject.Length > projectName.Length &&
configProject.StartsWith(projectName) &&
configProject[projectName.Length] == '=')
{
configuration = configProject.Substring(projectName.Length + 1);
break;
}
}
}
return configuration;
}
/// <summary>
/// Finds the common root between two paths
/// </summary>
/// <param name="path1"></param>
/// <param name="path2"></param>
/// <returns>common root on success, empty string on failure</returns>
private static string FindCommonRoot(string path1, string path2)
{
path1 = path1.TrimEnd(Path.DirectorySeparatorChar);
path2 = path2.TrimEnd(Path.DirectorySeparatorChar);
while (!String.IsNullOrEmpty(path1))
{
for (string searchPath = path2; !String.IsNullOrEmpty(searchPath); searchPath = Path.GetDirectoryName(searchPath))
{
if (path1.Equals(searchPath, StringComparison.OrdinalIgnoreCase))
{
return searchPath;
}
}
path1 = Path.GetDirectoryName(path1);
}
return path1;
}
/// <summary>
/// Finds the subfolder of a path, excluding a root and filename.
/// </summary>
/// <param name="path">Path to examine</param>
/// <param name="rootPath">Root that must be present </param>
/// <param name="fileName"></param>
/// <returns></returns>
private static string FindSubfolder(string path, string rootPath, string fileName)
{
if (Path.GetFileName(path).Equals(fileName, StringComparison.OrdinalIgnoreCase))
{
path = Path.GetDirectoryName(path);
}
if (path.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase))
{
// cut out the root and return the subpath
return path.Substring(rootPath.Length).Trim(Path.DirectorySeparatorChar);
}
return String.Empty;
}
private static string EnsureEndsWithBackslash(string dir)
{
if (dir[dir.Length - 1] != Path.DirectorySeparatorChar)
{
dir += Path.DirectorySeparatorChar;
}
return dir;
}
}
}

Просмотреть файл

@ -0,0 +1,192 @@
// 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.
#if false
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using WixToolset.Data;
/// <summary>
/// An MSBuild task to run the WiX compiler.
/// </summary>
public sealed class Candle : TaskBase
{
public string[] DefineConstants { get; set; }
public ITaskItem[] Extensions { get; set; }
public string[] IncludeSearchPaths { get; set; }
public string InstallerPlatform { get; set; }
[Output]
[Required]
public ITaskItem OutputFile { get; set; }
public bool Pedantic { get; set; }
public string PreprocessToFile { get; set; }
public bool PreprocessToStdOut { get; set; }
[Required]
public ITaskItem IntermediateDirectory { get; set; }
[Required]
public ITaskItem[] SourceFiles { get; set; }
public string ExtensionDirectory { get; set; }
public string[] ReferencePaths { get; set; }
protected override void ExecuteCore()
{
Messaging.Instance.InitializeAppName("WIX", "wix.exe");
Messaging.Instance.Display += this.DisplayMessage;
var preprocessor = new Preprocessor();
var compiler = new Compiler();
var sourceFiles = this.GatherSourceFiles();
var preprocessorVariables = this.GatherPreprocessorVariables();
foreach (var sourceFile in sourceFiles)
{
var document = preprocessor.Process(sourceFile.SourcePath, preprocessorVariables);
var intermediate = compiler.Compile(document);
intermediate.Save(sourceFile.OutputPath);
}
}
private void DisplayMessage(object sender, DisplayEventArgs e)
{
this.Log.LogMessageFromText(e.Message, MessageImportance.Normal);
}
private IEnumerable<SourceFile> GatherSourceFiles()
{
var files = new List<SourceFile>();
foreach (var item in this.SourceFiles)
{
var sourcePath = item.ItemSpec;
var outputPath = item.GetMetadata("CandleOutput") ?? this.OutputFile?.ItemSpec;
if (String.IsNullOrEmpty(outputPath))
{
outputPath = Path.Combine(this.IntermediateDirectory.ItemSpec, Path.GetFileNameWithoutExtension(sourcePath) + ".wir");
}
files.Add(new SourceFile(sourcePath, outputPath));
}
return files;
}
private IDictionary<string, string> GatherPreprocessorVariables()
{
var variables = new Dictionary<string, string>();
foreach (var pair in this.DefineConstants)
{
string[] value = pair.Split(new[] { '=' }, 2);
if (variables.ContainsKey(value[0]))
{
//Messaging.Instance.OnMessage(WixErrors.DuplicateVariableDefinition(value[0], (1 == value.Length) ? String.Empty : value[1], this.PreprocessorVariables[value[0]]));
break;
}
if (1 == value.Length)
{
variables.Add(value[0], String.Empty);
}
else
{
variables.Add(value[0], value[1]);
}
}
return variables;
}
///// <summary>
///// Builds a command line from options in this task.
///// </summary>
//protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
//{
// base.BuildCommandLine(commandLineBuilder);
// commandLineBuilder.AppendIfTrue("-p", this.PreprocessToStdOut);
// commandLineBuilder.AppendSwitchIfNotNull("-p", this.PreprocessToFile);
// commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
// commandLineBuilder.AppendArrayIfNotNull("-d", this.DefineConstants);
// commandLineBuilder.AppendArrayIfNotNull("-I", this.IncludeSearchPaths);
// commandLineBuilder.AppendIfTrue("-pedantic", this.Pedantic);
// commandLineBuilder.AppendSwitchIfNotNull("-arch ", this.InstallerPlatform);
// commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.referencePaths);
// commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
// // Support per-source-file output by looking at the SourceFiles items to
// // see if there is any "CandleOutput" metadata. If there is, we do our own
// // appending, otherwise we fall back to the built-in "append file names" code.
// // Note also that the wix.targets "Compile" target does *not* automagically
// // fix the "@(CompileObjOutput)" list to include these new output names.
// // If you really want to use this, you're going to have to clone the target
// // in your own .targets file and create the output list yourself.
// bool usePerSourceOutput = false;
// if (this.SourceFiles != null)
// {
// foreach (ITaskItem item in this.SourceFiles)
// {
// if (!String.IsNullOrEmpty(item.GetMetadata("CandleOutput")))
// {
// usePerSourceOutput = true;
// break;
// }
// }
// }
// if (usePerSourceOutput)
// {
// string[] newSourceNames = new string[this.SourceFiles.Length];
// for (int iSource = 0; iSource < this.SourceFiles.Length; ++iSource)
// {
// ITaskItem item = this.SourceFiles[iSource];
// if (null == item)
// {
// newSourceNames[iSource] = null;
// }
// else
// {
// string output = item.GetMetadata("CandleOutput");
// if (!String.IsNullOrEmpty(output))
// {
// newSourceNames[iSource] = String.Concat(item.ItemSpec, ";", output);
// }
// else
// {
// newSourceNames[iSource] = item.ItemSpec;
// }
// }
// }
// commandLineBuilder.AppendFileNamesIfNotNull(newSourceNames, " ");
// }
// else
// {
// commandLineBuilder.AppendFileNamesIfNotNull(this.SourceFiles, " ");
// }
//}
}
}
#endif

Просмотреть файл

@ -0,0 +1,342 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using WixToolset.Core;
using WixToolset.Data;
using WixToolset.Extensibility;
using WixToolset.Extensibility.Services;
/// <summary>
/// An MSBuild task to run the WiX compiler.
/// </summary>
public sealed class DoIt : Task
{
public string AdditionalOptions { get; set; }
public string[] Cultures { get; set; }
public string[] DefineConstants { get; set; }
public ITaskItem[] Extensions { get; set; }
public string ExtensionDirectory { get; set; }
public string[] IncludeSearchPaths { get; set; }
public string InstallerPlatform { get; set; }
[Required]
public ITaskItem IntermediateDirectory { get; set; }
public ITaskItem[] LocalizationFiles { get; set; }
public bool NoLogo { get; set; }
public ITaskItem[] LibraryFiles { get; set; }
[Output]
[Required]
public ITaskItem OutputFile { get; set; }
public string OutputType { get; set; }
public string PdbOutputFile { get; set; }
public bool Pedantic { get; set; }
[Required]
public ITaskItem[] SourceFiles { get; set; }
public string[] ReferencePaths { get; set; }
/// <summary>
/// Gets or sets whether all warnings should be suppressed.
/// </summary>
public bool SuppressAllWarnings { get; set; }
/// <summary>
/// Gets or sets a list of specific warnings to be suppressed.
/// </summary>
public string[] SuppressSpecificWarnings { get; set; }
/// <summary>
/// Gets or sets whether all warnings should be treated as errors.
/// </summary>
public bool TreatWarningsAsErrors { get; set; }
/// <summary>
/// Gets or sets a list of specific warnings to treat as errors.
/// </summary>
public string[] TreatSpecificWarningsAsErrors { get; set; }
/// <summary>
/// Gets or sets whether to display verbose output.
/// </summary>
public bool VerboseOutput { get; set; }
public ITaskItem[] BindInputPaths { get; set; }
public bool BindFiles { get; set; }
public ITaskItem BindContentsFile { get; set; }
public ITaskItem BindOutputsFile { get; set; }
public ITaskItem BindBuiltOutputsFile { get; set; }
public string CabinetCachePath { get; set; }
public int CabinetCreationThreadCount { get; set; }
public string DefaultCompressionLevel { get; set; }
[Output]
public ITaskItem UnreferencedSymbolsFile { get; set; }
public ITaskItem WixProjectFile { get; set; }
public string[] WixVariables { get; set; }
public bool SuppressValidation { get; set; }
public string[] SuppressIces { get; set; }
public string AdditionalCub { get; set; }
public override bool Execute()
{
try
{
this.ExecuteCore();
}
catch (Exception e)
{
this.Log.LogErrorFromException(e);
if (e is NullReferenceException || e is SEHException)
{
throw;
}
}
return !this.Log.HasLoggedErrors;
}
private void ExecuteCore()
{
var listener = new MsbuildMessageListener(this.Log, "WIX", this.BuildEngine.ProjectFileOfTaskNode);
var commandLineBuilder = new WixCommandLineBuilder();
commandLineBuilder.AppendTextUnquoted("build");
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendSwitchIfNotNull("-outputType ", this.OutputType);
commandLineBuilder.AppendIfTrue("-nologo", this.NoLogo);
commandLineBuilder.AppendArrayIfNotNull("-culture ", this.Cultures);
commandLineBuilder.AppendArrayIfNotNull("-d ", this.DefineConstants);
commandLineBuilder.AppendArrayIfNotNull("-I ", this.IncludeSearchPaths);
commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.ReferencePaths);
commandLineBuilder.AppendIfTrue("-sval", this.SuppressValidation);
commandLineBuilder.AppendArrayIfNotNull("-sice ", this.SuppressIces);
commandLineBuilder.AppendSwitchIfNotNull("-usf ", this.UnreferencedSymbolsFile);
commandLineBuilder.AppendSwitchIfNotNull("-cc ", this.CabinetCachePath);
commandLineBuilder.AppendSwitchIfNotNull("-intermediatefolder ", this.IntermediateDirectory);
commandLineBuilder.AppendSwitchIfNotNull("-contentsfile ", this.BindContentsFile);
commandLineBuilder.AppendSwitchIfNotNull("-outputsfile ", this.BindOutputsFile);
commandLineBuilder.AppendSwitchIfNotNull("-builtoutputsfile ", this.BindBuiltOutputsFile);
commandLineBuilder.AppendIfTrue("-bindFiles", this.BindFiles);
commandLineBuilder.AppendArrayIfNotNull("-bindPath ", this.CalculateBindPathStrings());
commandLineBuilder.AppendArrayIfNotNull("-loc ", this.LocalizationFiles);
commandLineBuilder.AppendArrayIfNotNull("-lib ", this.LibraryFiles);
commandLineBuilder.AppendTextIfNotWhitespace(this.AdditionalOptions);
commandLineBuilder.AppendFileNamesIfNotNull(this.SourceFiles, " ");
var commandLineString = commandLineBuilder.ToString();
this.Log.LogMessage(MessageImportance.Normal, "wix.exe " + commandLineString);
var serviceProvider = new WixToolsetServiceProvider();
var messaging = serviceProvider.GetService<IMessaging>();
messaging.SetListener(listener);
var arguments = serviceProvider.GetService<ICommandLineArguments>();
arguments.Populate(commandLineString);
var context = serviceProvider.GetService<ICommandLineContext>();
context.Messaging = messaging;
context.ExtensionManager = this.CreateExtensionManagerWithStandardBackends(serviceProvider, arguments.Extensions);
context.Arguments = arguments;
var commandLine = serviceProvider.GetService<ICommandLine>();
var command = commandLine.ParseStandardCommandLine(context);
command?.Execute();
}
private IExtensionManager CreateExtensionManagerWithStandardBackends(IServiceProvider serviceProvider, string[] extensions)
{
var extensionManager = serviceProvider.GetService<IExtensionManager>();
foreach (var type in new[] { typeof(WixToolset.Core.Burn.WixToolsetStandardBackend), typeof(WixToolset.Core.WindowsInstaller.WixToolsetStandardBackend) })
{
extensionManager.Add(type.Assembly);
}
foreach (var extension in extensions)
{
extensionManager.Load(extension);
}
return extensionManager;
}
private void DisplayMessage(object sender, DisplayEventArgs e)
{
this.Log.LogMessageFromText(e.Message, MessageImportance.Normal);
}
private IEnumerable<string> CalculateBindPathStrings()
{
if (null != this.BindInputPaths)
{
foreach (var item in this.BindInputPaths)
{
var path = item.GetMetadata("FullPath");
var bindName = item.GetMetadata("BindName");
if (!String.IsNullOrEmpty(bindName))
{
yield return String.Concat(bindName, "=", path);
}
else
{
yield return path;
}
}
}
}
///// <summary>
///// Builds a command line from options in this task.
///// </summary>
//protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
//{
// base.BuildCommandLine(commandLineBuilder);
// commandLineBuilder.AppendIfTrue("-p", this.PreprocessToStdOut);
// commandLineBuilder.AppendSwitchIfNotNull("-p", this.PreprocessToFile);
// commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
// commandLineBuilder.AppendArrayIfNotNull("-d", this.DefineConstants);
// commandLineBuilder.AppendArrayIfNotNull("-I", this.IncludeSearchPaths);
// commandLineBuilder.AppendIfTrue("-pedantic", this.Pedantic);
// commandLineBuilder.AppendSwitchIfNotNull("-arch ", this.InstallerPlatform);
// commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.referencePaths);
// commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
// // Support per-source-file output by looking at the SourceFiles items to
// // see if there is any "CandleOutput" metadata. If there is, we do our own
// // appending, otherwise we fall back to the built-in "append file names" code.
// // Note also that the wix.targets "Compile" target does *not* automagically
// // fix the "@(CompileObjOutput)" list to include these new output names.
// // If you really want to use this, you're going to have to clone the target
// // in your own .targets file and create the output list yourself.
// bool usePerSourceOutput = false;
// if (this.SourceFiles != null)
// {
// foreach (ITaskItem item in this.SourceFiles)
// {
// if (!String.IsNullOrEmpty(item.GetMetadata("CandleOutput")))
// {
// usePerSourceOutput = true;
// break;
// }
// }
// }
// if (usePerSourceOutput)
// {
// string[] newSourceNames = new string[this.SourceFiles.Length];
// for (int iSource = 0; iSource < this.SourceFiles.Length; ++iSource)
// {
// ITaskItem item = this.SourceFiles[iSource];
// if (null == item)
// {
// newSourceNames[iSource] = null;
// }
// else
// {
// string output = item.GetMetadata("CandleOutput");
// if (!String.IsNullOrEmpty(output))
// {
// newSourceNames[iSource] = String.Concat(item.ItemSpec, ";", output);
// }
// else
// {
// newSourceNames[iSource] = item.ItemSpec;
// }
// }
// }
// commandLineBuilder.AppendFileNamesIfNotNull(newSourceNames, " ");
// }
// else
// {
// commandLineBuilder.AppendFileNamesIfNotNull(this.SourceFiles, " ");
// }
//}
private class MsbuildMessageListener : IMessageListener
{
public MsbuildMessageListener(TaskLoggingHelper logger, string shortName, string longName)
{
this.Logger = logger;
this.ShortAppName = shortName;
this.LongAppName = longName;
}
public string ShortAppName { get; }
public string LongAppName { get; }
private TaskLoggingHelper Logger { get; }
public void Write(Message message)
{
switch (message.Level)
{
case MessageLevel.Error:
this.Logger.LogError(null, this.ShortAppName + message.Id.ToString(), null, message.SourceLineNumbers?.FileName ?? this.LongAppName, message.SourceLineNumbers?.LineNumber ?? 0, 0, 0, 0, message.ResourceNameOrFormat, message.MessageArgs);
break;
case MessageLevel.Warning:
this.Logger.LogWarning(null, this.ShortAppName + message.Id.ToString(), null, message.SourceLineNumbers?.FileName ?? this.LongAppName, message.SourceLineNumbers?.LineNumber ?? 0, 0, 0, 0, message.ResourceNameOrFormat, message.MessageArgs);
break;
default:
// TODO: Revisit this because something is going horribly awry. The commented out LogMessage call is crashing saying that the "message" parameter is null. When you look at the call stack, the code
// is in the wrong LogMessage override and the "null" subcategory was passed in as the message. Not clear why it is picking the wrong overload.
//if (message.Id > 0)
//{
// this.Logger.LogMessage(null, code, null, message.SourceLineNumber?.FileName, message.SourceLineNumber?.LineNumber ?? 0, 0, 0, 0, MessageImportance.Normal, message.Format, message.FormatData);
//}
//else
//{
this.Logger.LogMessage(MessageImportance.Normal, message.ResourceNameOrFormat, message.MessageArgs);
//}
break;
}
}
public void Write(string message)
{
this.Logger.LogMessage(MessageImportance.Low, message);
}
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
/// <summary>
/// Contains helper methods on searching for files
/// </summary>
public static class FileSearchHelperMethods
{
/// <summary>
/// Searches for the existence of a file in multiple directories.
/// Search is satisfied if default file path is valid and exists. If not,
/// file name is extracted from default path and combined with each of the directories
/// looking to see if it exists. If not found, input default path is returned.
/// </summary>
/// <param name="directories">Array of directories to look in, without filenames in them</param>
/// <param name="defaultFullPath">Default path - to use if not found</param>
/// <returns>File path if file found. Empty string if not found</returns>
public static string SearchFilePaths(string[] directories, string defaultFullPath)
{
if (String.IsNullOrEmpty(defaultFullPath))
{
return String.Empty;
}
if (File.Exists(defaultFullPath))
{
return defaultFullPath;
}
if (directories == null)
{
return string.Empty;
}
string fileName = Path.GetFileName(defaultFullPath);
foreach (string currentPath in directories)
{
if (String.IsNullOrEmpty(currentPath) || String.IsNullOrEmpty(currentPath.Trim()))
{
continue;
}
if (File.Exists(Path.Combine(currentPath, fileName)))
{
return Path.Combine(currentPath, fileName);
}
}
return String.Empty;
}
}
}

Просмотреть файл

@ -0,0 +1,146 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// This task generates metadata on the for compile output objects.
/// </summary>
public class GenerateCompileWithObjectPath : Task
{
/// <summary>
/// The list of files to generate outputs for.
/// </summary>
[Required]
public ITaskItem[] Compile
{
get;
set;
}
/// <summary>
/// The list of files with ObjectPath metadata.
/// </summary>
[Output]
public ITaskItem[] CompileWithObjectPath
{
get;
private set;
}
/// <summary>
/// The folder under which all ObjectPaths should reside.
/// </summary>
[Required]
public string IntermediateOutputPath
{
get;
set;
}
/// <summary>
/// Generate an identifier by hashing data from the row.
/// </summary>
/// <param name="prefix">Three letter or less prefix for generated row identifier.</param>
/// <param name="args">Information to hash.</param>
/// <returns>The generated identifier.</returns>
[SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")]
public static string GenerateIdentifier(string prefix, params string[] args)
{
string stringData = String.Join("|", args);
byte[] data = Encoding.Unicode.GetBytes(stringData);
// hash the data
byte[] hash;
using (MD5 md5 = new MD5CryptoServiceProvider())
{
hash = md5.ComputeHash(data);
}
// build up the identifier
StringBuilder identifier = new StringBuilder(35, 35);
identifier.Append(prefix);
// hard coded to 16 as that is the most bytes that can be used to meet the length requirements. SHA1 is 20 bytes.
for (int i = 0; i < 16; i++)
{
identifier.Append(hash[i].ToString("X2", CultureInfo.InvariantCulture.NumberFormat));
}
return identifier.ToString();
}
/// <summary>
/// Gets the full path of the directory in which the file is found.
/// </summary>
/// <param name='file'>The file from which to extract the directory.</param>
/// <returns>The generated identifier.</returns>
private static string GetDirectory(ITaskItem file)
{
return file.GetMetadata("RootDir") + file.GetMetadata("Directory");
}
/// <summary>
/// Sets the object path to use for the file.
/// </summary>
/// <param name='file'>The file on which to set the ObjectPath metadata.</param>
/// <remarks>
/// For the same input path it will return the same ObjectPath. Case is not ignored, however that isn't a problem.
/// </remarks>
private void SetObjectPath(ITaskItem file)
{
// If the source file is in the project directory or in the intermediate directory, use the intermediate directory.
if (string.IsNullOrEmpty(file.GetMetadata("RelativeDir")) || string.Compare(file.GetMetadata("RelativeDir"), this.IntermediateOutputPath, StringComparison.OrdinalIgnoreCase) == 0)
{
file.SetMetadata("ObjectPath", this.IntermediateOutputPath);
}
// Otherwise use a subdirectory of the intermediate directory. The subfolder's name is based on the full path of the folder containing the source file.
else
{
file.SetMetadata("ObjectPath", Path.Combine(this.IntermediateOutputPath, GenerateIdentifier("pth", GetDirectory(file))) + Path.DirectorySeparatorChar);
}
}
/// <summary>
/// Gets a complete list of external cabs referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
if (string.IsNullOrEmpty(this.IntermediateOutputPath))
{
this.Log.LogError("IntermediateOutputPath parameter is required and cannot be empty");
return false;
}
if (this.Compile == null || this.Compile.Length == 0)
{
return true;
}
this.CompileWithObjectPath = new ITaskItem[this.Compile.Length];
for (int i = 0; i < this.Compile.Length; ++i)
{
this.CompileWithObjectPath[i] = new TaskItem(this.Compile[i].ItemSpec, this.Compile[i].CloneCustomMetadata());
// Do not overwrite the ObjectPath metadata if it already was set.
if (string.IsNullOrEmpty(this.CompileWithObjectPath[i].GetMetadata("ObjectPath")))
{
SetObjectPath(this.CompileWithObjectPath[i]);
}
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,87 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using WixToolset.Dtf.WindowsInstaller;
using Microsoft.Win32;
/// <summary>
/// This task assigns Culture metadata to files based on the value of the Culture attribute on the
/// WixLocalization element inside the file.
/// </summary>
public class GetCabList : Task
{
private ITaskItem database;
private ITaskItem[] cabList;
/// <summary>
/// The list of database files to find cabs in
/// </summary>
[Required]
public ITaskItem Database
{
get { return this.database; }
set { this.database = value; }
}
/// <summary>
/// The total list of cabs in this database
/// </summary>
[Output]
public ITaskItem[] CabList
{
get { return this.cabList; }
}
/// <summary>
/// Gets a complete list of external cabs referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
string databaseFile = this.database.ItemSpec;
Object []args = { };
System.Collections.Generic.List<ITaskItem> cabNames = new System.Collections.Generic.List<ITaskItem>();
// If the file doesn't exist, no cabs to return, so exit now
if (!File.Exists(databaseFile))
{
return true;
}
using (Database database = new Database(databaseFile))
{
// If the media table doesn't exist, no cabs to return, so exit now
if (null == database.Tables["Media"])
{
return true;
}
System.Collections.IList records = database.ExecuteQuery("SELECT `Cabinet` FROM `Media`", args);
foreach (string cabName in records)
{
if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal))
{
continue;
}
cabNames.Add(new TaskItem(Path.Combine(Path.GetDirectoryName(databaseFile), cabName)));
}
}
this.cabList = cabNames.ToArray();
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,230 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using WixToolset.Dtf.WindowsInstaller;
using Microsoft.Win32;
/// <summary>
/// This task assigns Culture metadata to files based on the value of the Culture attribute on the
/// WixLocalization element inside the file.
/// </summary>
public class GetLooseFileList : Task
{
private ITaskItem database;
private ITaskItem[] looseFileList;
internal const int MsidbFileAttributesNoncompressed = 8192;
internal const int MsidbFileAttributesCompressed = 16384;
/// <summary>
/// The list of database files to find Loose Files in
/// </summary>
[Required]
public ITaskItem Database
{
get { return this.database; }
set { this.database = value; }
}
/// <summary>
/// The total list of Loose Files in this database
/// </summary>
[Output]
public ITaskItem[] LooseFileList
{
get { return this.looseFileList; }
}
/// <summary>
/// Takes the "defaultDir" column
/// </summary>
/// <returns>Returns the corresponding sourceDir.</returns>
public string SourceDirFromDefaultDir(string defaultDir)
{
string sourceDir;
string[] splitted = defaultDir.Split(':');
if (1 == splitted.Length)
{
sourceDir = splitted[0];
}
else
{
sourceDir = splitted[1];
}
splitted = sourceDir.Split('|');
if (1 == splitted.Length)
{
sourceDir = splitted[0];
}
else
{
sourceDir = splitted[1];
}
return sourceDir;
}
/// <summary>
/// Takes the "FileName" column
/// </summary>
/// <returns>Returns the corresponding source file name.</returns>
public string SourceFileFromFileName(string fileName)
{
string sourceFile;
string[] splitted = fileName.Split('|');
if (1 == splitted.Length)
{
sourceFile = splitted[0];
}
else
{
sourceFile = splitted[1];
}
return sourceFile;
}
/// <summary>
/// Gets a complete list of external Loose Files referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
string databaseFile = this.database.ItemSpec;
Object []emptyArgs = { };
System.Collections.Generic.List<ITaskItem> looseFileNames = new System.Collections.Generic.List<ITaskItem>();
Dictionary<string, string> ComponentFullDirectory = new Dictionary<string, string>();
Dictionary<string, string> DirectoryIdDefaultDir = new Dictionary<string, string>();
Dictionary<string, string> DirectoryIdParent = new Dictionary<string, string>();
Dictionary<string, string> DirectoryIdFullSource = new Dictionary<string, string>();
int i;
string databaseDir = Path.GetDirectoryName(databaseFile);
// If the file doesn't exist, no Loose Files to return, so exit now
if (!File.Exists(databaseFile))
{
return true;
}
using (Database database = new Database(databaseFile))
{
bool compressed = false;
if (2 == (database.SummaryInfo.WordCount & 2))
{
compressed = true;
}
// If the media table doesn't exist, no Loose Files to return, so exit now
if (null == database.Tables["File"])
{
return true;
}
// Only setup all these helpful indexes if the database is marked as uncompressed. If it's marked as compressed, files are stored at the root,
// so none of these indexes will be used
if (!compressed)
{
if (null == database.Tables["Directory"] || null == database.Tables["Component"])
{
return true;
}
System.Collections.IList directoryRecords = database.ExecuteQuery("SELECT `Directory`,`Directory_Parent`,`DefaultDir` FROM `Directory`", emptyArgs);
// First setup a simple index from DirectoryId to DefaultDir
for (i = 0; i < directoryRecords.Count; i += 3)
{
string directoryId = (string)(directoryRecords[i]);
string directoryParent = (string)(directoryRecords[i + 1]);
string defaultDir = (string)(directoryRecords[i + 2]);
string sourceDir = SourceDirFromDefaultDir(defaultDir);
DirectoryIdDefaultDir[directoryId] = sourceDir;
DirectoryIdParent[directoryId] = directoryParent;
}
// Setup an index from directory Id to the full source path
for (i = 0; i < directoryRecords.Count; i += 3)
{
string directoryId = (string)(directoryRecords[i]);
string directoryParent = (string)(directoryRecords[i + 1]);
string defaultDir = (string)(directoryRecords[i + 2]);
string sourceDir = DirectoryIdDefaultDir[directoryId];
// The TARGETDIR case
if (String.IsNullOrEmpty(directoryParent))
{
DirectoryIdFullSource[directoryId] = databaseDir;
}
else
{
string tempDirectoryParent = directoryParent;
while (!String.IsNullOrEmpty(tempDirectoryParent) && !String.IsNullOrEmpty(DirectoryIdParent[tempDirectoryParent]))
{
sourceDir = Path.Combine(DirectoryIdDefaultDir[tempDirectoryParent], sourceDir);
tempDirectoryParent = DirectoryIdParent[tempDirectoryParent];
}
DirectoryIdFullSource[directoryId] = Path.Combine(databaseDir, sourceDir);
}
}
// Setup an index from component Id to full directory path
System.Collections.IList componentRecords = database.ExecuteQuery("SELECT `Component`,`Directory_` FROM `Component`", emptyArgs);
for (i = 0; i < componentRecords.Count; i += 2)
{
string componentId = (string)(componentRecords[i]);
string componentDir = (string)(componentRecords[i + 1]);
ComponentFullDirectory[componentId] = DirectoryIdFullSource[componentDir];
}
}
System.Collections.IList fileRecords = database.ExecuteQuery("SELECT `Component_`,`FileName`,`Attributes` FROM `File`", emptyArgs);
for (i = 0; i < fileRecords.Count; i += 3)
{
string componentId = (string)(fileRecords[i]);
string fileName = SourceFileFromFileName((string)(fileRecords[i + 1]));
int attributes = (int)(fileRecords[i + 2]);
// If the whole database is marked uncompressed, use the directory layout made above
if ((!compressed && MsidbFileAttributesCompressed != (attributes & MsidbFileAttributesCompressed)))
{
looseFileNames.Add(new TaskItem(Path.GetFullPath(Path.Combine(ComponentFullDirectory[componentId], fileName))));
}
// If the database is marked as compressed, put files at the root
else if (compressed && (MsidbFileAttributesNoncompressed == (attributes & MsidbFileAttributesNoncompressed)))
{
looseFileNames.Add(new TaskItem(Path.GetFullPath(Path.Combine(databaseDir, fileName))));
}
}
}
this.looseFileList = looseFileNames.ToArray();
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
// 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.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "WixToolset")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Msi", Scope = "namespace", Target = "WixToolset.BuildTasks")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "wix")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wix")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "wix")]

Просмотреть файл

@ -0,0 +1,103 @@
// 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.
namespace WixToolset.BuildTasks
{
using Microsoft.Build.Framework;
public sealed class HeatDirectory : HeatTask
{
private string directory;
private bool keepEmptyDirectories;
private bool suppressCom;
private bool suppressRootDirectory;
private bool suppressRegistry;
private string template;
private string componentGroupName;
private string directoryRefId;
private string preprocessorVariable;
public string ComponentGroupName
{
get { return this.componentGroupName; }
set { this.componentGroupName = value; }
}
[Required]
public string Directory
{
get { return this.directory; }
set { this.directory = value; }
}
public string DirectoryRefId
{
get { return this.directoryRefId; }
set { this.directoryRefId = value; }
}
public bool KeepEmptyDirectories
{
get { return this.keepEmptyDirectories; }
set { this.keepEmptyDirectories = value; }
}
public string PreprocessorVariable
{
get { return this.preprocessorVariable; }
set { this.preprocessorVariable = value; }
}
public bool SuppressCom
{
get { return this.suppressCom; }
set { this.suppressCom = value; }
}
public bool SuppressRootDirectory
{
get { return this.suppressRootDirectory; }
set { this.suppressRootDirectory = value; }
}
public bool SuppressRegistry
{
get { return this.suppressRegistry; }
set { this.suppressRegistry = value; }
}
public string Template
{
get { return this.template; }
set { this.template = value; }
}
protected override string OperationName
{
get { return "dir"; }
}
/// <summary>
/// Generate the command line arguments to write to the response file from the properties.
/// </summary>
/// <returns>Command line string.</returns>
protected override string GenerateResponseFileCommands()
{
WixCommandLineBuilder commandLineBuilder = new WixCommandLineBuilder();
commandLineBuilder.AppendSwitch(this.OperationName);
commandLineBuilder.AppendFileNameIfNotNull(this.Directory);
commandLineBuilder.AppendSwitchIfNotNull("-cg ", this.ComponentGroupName);
commandLineBuilder.AppendSwitchIfNotNull("-dr ", this.DirectoryRefId);
commandLineBuilder.AppendIfTrue("-ke", this.KeepEmptyDirectories);
commandLineBuilder.AppendIfTrue("-scom", this.SuppressCom);
commandLineBuilder.AppendIfTrue("-sreg", this.SuppressRegistry);
commandLineBuilder.AppendIfTrue("-srd", this.SuppressRootDirectory);
commandLineBuilder.AppendSwitchIfNotNull("-template ", this.Template);
commandLineBuilder.AppendSwitchIfNotNull("-var ", this.PreprocessorVariable);
base.BuildCommandLine(commandLineBuilder);
return commandLineBuilder.ToString();
}
}
}

Просмотреть файл

@ -0,0 +1,95 @@
// 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.
namespace WixToolset.BuildTasks
{
using Microsoft.Build.Framework;
public sealed class HeatFile : HeatTask
{
private string file;
private bool suppressCom;
private bool suppressRegistry;
private bool suppressRootDirectory;
private string template;
private string componentGroupName;
private string directoryRefId;
private string preprocessorVariable;
public string ComponentGroupName
{
get { return this.componentGroupName; }
set { this.componentGroupName = value; }
}
public string DirectoryRefId
{
get { return this.directoryRefId; }
set { this.directoryRefId = value; }
}
[Required]
public string File
{
get { return this.file; }
set { this.file = value; }
}
public string PreprocessorVariable
{
get { return this.preprocessorVariable; }
set { this.preprocessorVariable = value; }
}
public bool SuppressCom
{
get { return this.suppressCom; }
set { this.suppressCom = value; }
}
public bool SuppressRegistry
{
get { return this.suppressRegistry; }
set { this.suppressRegistry = value; }
}
public bool SuppressRootDirectory
{
get { return this.suppressRootDirectory; }
set { this.suppressRootDirectory = value; }
}
public string Template
{
get { return this.template; }
set { this.template = value; }
}
protected override string OperationName
{
get { return "file"; }
}
/// <summary>
/// Generate the command line arguments to write to the response file from the properties.
/// </summary>
/// <returns>Command line string.</returns>
protected override string GenerateResponseFileCommands()
{
WixCommandLineBuilder commandLineBuilder = new WixCommandLineBuilder();
commandLineBuilder.AppendSwitch(this.OperationName);
commandLineBuilder.AppendFileNameIfNotNull(this.File);
commandLineBuilder.AppendSwitchIfNotNull("-cg ", this.ComponentGroupName);
commandLineBuilder.AppendSwitchIfNotNull("-dr ", this.DirectoryRefId);
commandLineBuilder.AppendIfTrue("-scom", this.SuppressCom);
commandLineBuilder.AppendIfTrue("-srd", this.SuppressRootDirectory);
commandLineBuilder.AppendIfTrue("-sreg", this.SuppressRegistry);
commandLineBuilder.AppendSwitchIfNotNull("-template ", this.Template);
commandLineBuilder.AppendSwitchIfNotNull("-var ", this.PreprocessorVariable);
base.BuildCommandLine(commandLineBuilder);
return commandLineBuilder.ToString();
}
}
}

Просмотреть файл

@ -0,0 +1,108 @@
// 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.
namespace WixToolset.BuildTasks
{
using Microsoft.Build.Framework;
public sealed class HeatProject : HeatTask
{
private string configuration;
private string directoryIds;
private string generateType;
private bool generateWixVariables;
private string platform;
private string project;
private string projectName;
private string[] projectOutputGroups;
public string Configuration
{
get { return this.configuration; }
set { this.configuration = value; }
}
public string DirectoryIds
{
get { return this.directoryIds; }
set { this.directoryIds = value; }
}
public bool GenerateWixVariables
{
get { return this.generateWixVariables; }
set { this.generateWixVariables = value; }
}
public string GenerateType
{
get { return this.generateType; }
set { this.generateType = value; }
}
public string Platform
{
get { return this.platform; }
set { this.platform = value; }
}
[Required]
public string Project
{
get { return this.project; }
set { this.project = value; }
}
public string ProjectName
{
get { return this.projectName; }
set { this.projectName = value; }
}
public string[] ProjectOutputGroups
{
get
{
return this.projectOutputGroups;
}
set
{
this.projectOutputGroups = value;
// If it's just one string and it contains semicolons, let's
// split it into separate items.
if (this.projectOutputGroups.Length == 1)
{
this.projectOutputGroups = this.projectOutputGroups[0].Split(new char[] { ';' });
}
}
}
protected override string OperationName
{
get { return "project"; }
}
/// <summary>
/// Generate the command line arguments to write to the response file from the properties.
/// </summary>
/// <returns>Command line string.</returns>
protected override string GenerateResponseFileCommands()
{
WixCommandLineBuilder commandLineBuilder = new WixCommandLineBuilder();
commandLineBuilder.AppendSwitch(this.OperationName);
commandLineBuilder.AppendFileNameIfNotNull(this.Project);
commandLineBuilder.AppendSwitchIfNotNull("-configuration ", this.Configuration);
commandLineBuilder.AppendSwitchIfNotNull("-directoryid ", this.DirectoryIds);
commandLineBuilder.AppendSwitchIfNotNull("-generate ", this.GenerateType);
commandLineBuilder.AppendSwitchIfNotNull("-platform ", this.Platform);
commandLineBuilder.AppendArrayIfNotNull("-pog ", this.ProjectOutputGroups);
commandLineBuilder.AppendSwitchIfNotNull("-projectname ", this.ProjectName);
commandLineBuilder.AppendIfTrue("-wixvar", this.GenerateWixVariables);
base.BuildCommandLine(commandLineBuilder);
return commandLineBuilder.ToString();
}
}
}

Просмотреть файл

@ -0,0 +1,121 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// A base MSBuild task to run the WiX harvester.
/// Specific harvester tasks should extend this class.
/// </summary>
public abstract class HeatTask : WixToolTask
{
private const string HeatToolName = "Heat.exe";
private bool autogenerageGuids;
private bool generateGuidsNow;
private ITaskItem outputFile;
private bool suppressFragments;
private bool suppressUniqueIds;
private string[] transforms;
public bool AutogenerateGuids
{
get { return this.autogenerageGuids; }
set { this.autogenerageGuids = value; }
}
public bool GenerateGuidsNow
{
get { return this.generateGuidsNow; }
set { this.generateGuidsNow = value; }
}
[Required]
[Output]
public ITaskItem OutputFile
{
get { return this.outputFile; }
set { this.outputFile = value; }
}
public bool SuppressFragments
{
get { return this.suppressFragments; }
set { this.suppressFragments = value; }
}
public bool SuppressUniqueIds
{
get { return this.suppressUniqueIds; }
set { this.suppressUniqueIds = value; }
}
public string[] Transforms
{
get { return this.transforms; }
set { this.transforms = value; }
}
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of heat.exe.</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return HeatToolName; }
}
/// <summary>
/// Gets the name of the heat operation performed by the task.
/// </summary>
/// <remarks>This is the first parameter passed on the heat.exe command-line.</remarks>
/// <value>The name of the heat operation performed by the task.</value>
protected abstract string OperationName
{
get;
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply heat.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return HeatToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), HeatToolName);
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
base.BuildCommandLine(commandLineBuilder);
commandLineBuilder.AppendIfTrue("-ag", this.AutogenerateGuids);
commandLineBuilder.AppendIfTrue("-gg", this.GenerateGuidsNow);
commandLineBuilder.AppendIfTrue("-nologo", this.NoLogo);
commandLineBuilder.AppendIfTrue("-sfrag", this.SuppressFragments);
commandLineBuilder.AppendIfTrue("-suid", this.SuppressUniqueIds);
commandLineBuilder.AppendArrayIfNotNull("-sw", this.SuppressSpecificWarnings);
commandLineBuilder.AppendArrayIfNotNull("-t ", this.Transforms);
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
}
}
}

Просмотреть файл

@ -0,0 +1,118 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task to run the WiX transform generator.
/// </summary>
public sealed class Insignia : WixToolTask
{
private const string InsigniaToolName = "insignia.exe";
/// <summary>
/// Gets or sets the path to the database to inscribe.
/// </summary>
public ITaskItem DatabaseFile { get; set; }
/// <summary>
/// Gets or sets the path to the bundle to inscribe.
/// </summary>
public ITaskItem BundleFile { get; set; }
/// <summary>
/// Gets or sets the path to the original bundle that contains the attached container.
/// </summary>
public ITaskItem OriginalBundleFile { get; set; }
/// <summary>
/// Gets or sets the path to output the inscribed result.
/// </summary>
[Required]
public ITaskItem OutputFile { get; set; }
/// <summary>
/// Gets or sets the output. Only set if insignia does work.
/// </summary>
[Output]
public ITaskItem Output { get; set; }
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of Insignia.exe.</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return InsigniaToolName; }
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply Insignia.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return InsigniaToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), InsigniaToolName);
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
base.BuildCommandLine(commandLineBuilder);
commandLineBuilder.AppendSwitchIfNotNull("-im ", this.DatabaseFile);
if (null != this.OriginalBundleFile)
{
commandLineBuilder.AppendSwitchIfNotNull("-ab ", this.BundleFile);
commandLineBuilder.AppendFileNameIfNotNull(this.OriginalBundleFile);
}
else
{
commandLineBuilder.AppendSwitchIfNotNull("-ib ", this.BundleFile);
}
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
}
/// <summary>
/// Executes a tool in-process by loading the tool assembly and invoking its entrypoint.
/// </summary>
/// <param name="pathToTool">Path to the tool to be executed; must be a managed executable.</param>
/// <param name="responseFileCommands">Commands to be written to a response file.</param>
/// <param name="commandLineCommands">Commands to be passed directly on the command-line.</param>
/// <returns>The tool exit code.</returns>
protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
int returnCode = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
if (0 == returnCode) // successfully did work.
{
this.Output = this.OutputFile;
}
else if (-1 == returnCode) // no work done.
{
returnCode = 0;
}
return returnCode;
}
}
}

Просмотреть файл

@ -0,0 +1,488 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task to run the WiX linker.
/// </summary>
public sealed class Light : WixToolTask
{
private const string LightToolName = "Light.exe";
private string additionalCub;
private bool allowIdenticalRows;
private bool allowUnresolvedReferences;
private string[] baseInputPaths;
private ITaskItem[] bindInputPaths;
private bool backwardsCompatibleGuidGeneration;
private bool bindFiles;
private ITaskItem builtOutputsFile;
private string cabinetCachePath;
private int cabinetCreationThreadCount = WixCommandLineBuilder.Unspecified;
private ITaskItem contentsFile;
private string cultures;
private string customBinder;
private string defaultCompressionLevel;
private ITaskItem[] extensions;
private string[] ices;
private bool leaveTemporaryFiles;
private ITaskItem[] localizationFiles;
private ITaskItem[] objectFiles;
private bool outputAsXml;
private ITaskItem outputsFile;
private ITaskItem outputFile;
private ITaskItem pdbOutputFile;
private ITaskItem wixProjectFile;
private bool pedantic;
private bool reuseCabinetCache;
private bool suppressAclReset;
private bool suppressAssemblies;
private bool suppressDefaultAdminSequenceActions;
private bool suppressDefaultAdvSequenceActions;
private bool suppressDefaultUISequenceActions;
private bool dropUnrealTables;
private bool exactAssemblyVersions;
private bool suppressFileHashAndInfo;
private bool suppressFiles;
private bool suppressIntermediateFileVersionMatching;
private string[] suppressIces;
private bool suppressLayout;
private bool suppressLocalization;
private bool suppressMsiAssemblyTableProcessing;
private bool suppressPdbOutput;
private bool suppressSchemaValidation;
private bool suppressValidation;
private bool suppressTagSectionIdAttributeOnTuples;
private ITaskItem unreferencedSymbolsFile;
private string[] wixVariables;
private string extensionDirectory;
private string[] referencePaths;
/// <summary>
/// Creates a new light task.
/// </summary>
/// <remarks>
/// Defaults to running the task as a separate process, instead of in-proc
/// which is the default for WixToolTasks. This allows the Win32 manifest file
/// embedded in light.exe to enable reg-free COM interop with mergemod.dll.
/// </remarks>
public Light()
{
}
public string AdditionalCub
{
get { return this.additionalCub; }
set { this.additionalCub = value; }
}
public bool AllowIdenticalRows
{
get { return this.allowIdenticalRows; }
set { this.allowIdenticalRows = value; }
}
public bool AllowUnresolvedReferences
{
get { return this.allowUnresolvedReferences; }
set { this.allowUnresolvedReferences = value; }
}
// TODO: remove this property entirely in v4.0
[Obsolete("Use BindInputPaths instead of BaseInputPaths.")]
public string[] BaseInputPaths
{
get { return this.baseInputPaths; }
set { this.baseInputPaths = value; }
}
public ITaskItem[] BindInputPaths
{
get { return this.bindInputPaths; }
set { this.bindInputPaths = value; }
}
public bool BackwardsCompatibleGuidGeneration
{
get { return this.backwardsCompatibleGuidGeneration; }
set { this.backwardsCompatibleGuidGeneration = value; }
}
public bool BindFiles
{
get { return this.bindFiles; }
set { this.bindFiles = value; }
}
public string CabinetCachePath
{
get { return this.cabinetCachePath; }
set { this.cabinetCachePath = value; }
}
public int CabinetCreationThreadCount
{
get { return this.cabinetCreationThreadCount; }
set { this.cabinetCreationThreadCount = value; }
}
public ITaskItem BindBuiltOutputsFile
{
get { return this.builtOutputsFile; }
set { this.builtOutputsFile = value; }
}
public ITaskItem BindContentsFile
{
get { return this.contentsFile; }
set { this.contentsFile = value; }
}
public ITaskItem BindOutputsFile
{
get { return this.outputsFile; }
set { this.outputsFile = value; }
}
public string Cultures
{
get { return this.cultures; }
set { this.cultures = value; }
}
public string CustomBinder
{
get { return this.customBinder; }
set { this.customBinder = value; }
}
public string DefaultCompressionLevel
{
get { return this.defaultCompressionLevel; }
set { this.defaultCompressionLevel = value; }
}
public bool DropUnrealTables
{
get { return this.dropUnrealTables; }
set { this.dropUnrealTables = value; }
}
public bool ExactAssemblyVersions
{
get { return this.exactAssemblyVersions; }
set { this.exactAssemblyVersions = value; }
}
public ITaskItem[] Extensions
{
get { return this.extensions; }
set { this.extensions = value; }
}
public string[] Ices
{
get { return this.ices; }
set { this.ices = value; }
}
public bool LeaveTemporaryFiles
{
get { return this.leaveTemporaryFiles; }
set { this.leaveTemporaryFiles = value; }
}
public ITaskItem[] LocalizationFiles
{
get { return this.localizationFiles; }
set { this.localizationFiles = value; }
}
[Required]
public ITaskItem[] ObjectFiles
{
get { return this.objectFiles; }
set { this.objectFiles = value; }
}
public bool OutputAsXml
{
get { return this.outputAsXml; }
set { this.outputAsXml = value; }
}
[Required]
[Output]
public ITaskItem OutputFile
{
get { return this.outputFile; }
set { this.outputFile = value; }
}
[Output]
public ITaskItem PdbOutputFile
{
get { return this.pdbOutputFile; }
set { this.pdbOutputFile = value; }
}
public bool Pedantic
{
get { return this.pedantic; }
set { this.pedantic = value; }
}
public bool ReuseCabinetCache
{
get { return this.reuseCabinetCache; }
set { this.reuseCabinetCache = value; }
}
public bool SuppressAclReset
{
get { return this.suppressAclReset; }
set { this.suppressAclReset = value; }
}
public bool SuppressAssemblies
{
get { return this.suppressAssemblies; }
set { this.suppressAssemblies = value; }
}
public bool SuppressDefaultAdminSequenceActions
{
get { return this.suppressDefaultAdminSequenceActions; }
set { this.suppressDefaultAdminSequenceActions = value; }
}
public bool SuppressDefaultAdvSequenceActions
{
get { return this.suppressDefaultAdvSequenceActions; }
set { this.suppressDefaultAdvSequenceActions = value; }
}
public bool SuppressDefaultUISequenceActions
{
get { return this.suppressDefaultUISequenceActions; }
set { this.suppressDefaultUISequenceActions = value; }
}
public bool SuppressFileHashAndInfo
{
get { return this.suppressFileHashAndInfo; }
set { this.suppressFileHashAndInfo = value; }
}
public bool SuppressFiles
{
get { return this.suppressFiles; }
set { this.suppressFiles = value; }
}
public bool SuppressIntermediateFileVersionMatching
{
get { return this.suppressIntermediateFileVersionMatching; }
set { this.suppressIntermediateFileVersionMatching = value; }
}
public string[] SuppressIces
{
get { return this.suppressIces; }
set { this.suppressIces = value; }
}
public bool SuppressLayout
{
get { return this.suppressLayout; }
set { this.suppressLayout = value; }
}
public bool SuppressLocalization
{
get { return this.suppressLocalization; }
set { this.suppressLocalization = value; }
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public bool SuppressMsiAssemblyTableProcessing
{
get { return this.suppressMsiAssemblyTableProcessing; }
set { this.suppressMsiAssemblyTableProcessing = value; }
}
public bool SuppressPdbOutput
{
get { return this.suppressPdbOutput; }
set { this.suppressPdbOutput = value; }
}
public bool SuppressSchemaValidation
{
get { return this.suppressSchemaValidation; }
set { this.suppressSchemaValidation = value; }
}
public bool SuppressValidation
{
get { return this.suppressValidation; }
set { this.suppressValidation = value; }
}
public bool SuppressTagSectionIdAttributeOnTuples
{
get { return this.suppressTagSectionIdAttributeOnTuples; }
set { this.suppressTagSectionIdAttributeOnTuples = value; }
}
[Output]
public ITaskItem UnreferencedSymbolsFile
{
get { return this.unreferencedSymbolsFile; }
set { this.unreferencedSymbolsFile = value; }
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public ITaskItem WixProjectFile
{
get { return this.wixProjectFile; }
set { this.wixProjectFile = value; }
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public string[] WixVariables
{
get { return this.wixVariables; }
set { this.wixVariables = value; }
}
public string ExtensionDirectory
{
get { return this.extensionDirectory; }
set { this.extensionDirectory = value; }
}
public string[] ReferencePaths
{
get { return this.referencePaths; }
set { this.referencePaths = value; }
}
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of light.exe.</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return LightToolName; }
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply light.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return LightToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), LightToolName);
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
// Always put the output first so it is easy to find in the log.
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendSwitchIfNotNull("-pdbout ", this.PdbOutputFile);
base.BuildCommandLine(commandLineBuilder);
commandLineBuilder.AppendIfTrue("-ai", this.AllowIdenticalRows);
commandLineBuilder.AppendIfTrue("-au", this.AllowUnresolvedReferences);
commandLineBuilder.AppendArrayIfNotNull("-b ", this.baseInputPaths);
if (null != this.BindInputPaths)
{
Queue<String> formattedBindInputPaths = new Queue<String>();
foreach (ITaskItem item in this.BindInputPaths)
{
String formattedPath = string.Empty;
String bindName = item.GetMetadata("BindName");
if (!String.IsNullOrEmpty(bindName))
{
formattedPath = String.Concat(bindName, "=", item.GetMetadata("FullPath"));
}
else
{
formattedPath = item.GetMetadata("FullPath");
}
formattedBindInputPaths.Enqueue(formattedPath);
}
commandLineBuilder.AppendArrayIfNotNull("-b ", formattedBindInputPaths.ToArray());
}
commandLineBuilder.AppendIfTrue("-bcgg", this.BackwardsCompatibleGuidGeneration);
commandLineBuilder.AppendIfTrue("-bf", this.BindFiles);
commandLineBuilder.AppendSwitchIfNotNull("-cc ", this.CabinetCachePath);
commandLineBuilder.AppendIfSpecified("-ct ", this.CabinetCreationThreadCount);
commandLineBuilder.AppendSwitchIfNotNull("-cub ", this.AdditionalCub);
commandLineBuilder.AppendSwitchIfNotNull("-cultures:", this.Cultures);
commandLineBuilder.AppendSwitchIfNotNull("-binder ", this.CustomBinder);
commandLineBuilder.AppendArrayIfNotNull("-d", this.WixVariables);
commandLineBuilder.AppendSwitchIfNotNull("-dcl:", this.DefaultCompressionLevel);
commandLineBuilder.AppendIfTrue("-dut", this.DropUnrealTables);
commandLineBuilder.AppendIfTrue("-eav", this.ExactAssemblyVersions);
commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.referencePaths);
commandLineBuilder.AppendArrayIfNotNull("-ice:", this.Ices);
commandLineBuilder.AppendArrayIfNotNull("-loc ", this.LocalizationFiles);
commandLineBuilder.AppendIfTrue("-notidy", this.LeaveTemporaryFiles);
commandLineBuilder.AppendIfTrue("-pedantic", this.Pedantic);
commandLineBuilder.AppendIfTrue("-reusecab", this.ReuseCabinetCache);
commandLineBuilder.AppendIfTrue("-sa", this.SuppressAssemblies);
commandLineBuilder.AppendIfTrue("-sacl", this.SuppressAclReset);
commandLineBuilder.AppendIfTrue("-sadmin", this.SuppressDefaultAdminSequenceActions);
commandLineBuilder.AppendIfTrue("-sadv", this.SuppressDefaultAdvSequenceActions);
commandLineBuilder.AppendArrayIfNotNull("-sice:", this.SuppressIces);
commandLineBuilder.AppendIfTrue("-sma", this.SuppressMsiAssemblyTableProcessing);
commandLineBuilder.AppendIfTrue("-sf", this.SuppressFiles);
commandLineBuilder.AppendIfTrue("-sh", this.SuppressFileHashAndInfo);
commandLineBuilder.AppendIfTrue("-sl", this.SuppressLayout);
commandLineBuilder.AppendIfTrue("-sloc", this.SuppressLocalization);
commandLineBuilder.AppendIfTrue("-spdb", this.SuppressPdbOutput);
commandLineBuilder.AppendIfTrue("-ss", this.SuppressSchemaValidation);
commandLineBuilder.AppendIfTrue("-sts", this.SuppressTagSectionIdAttributeOnTuples);
commandLineBuilder.AppendIfTrue("-sui", this.SuppressDefaultUISequenceActions);
commandLineBuilder.AppendIfTrue("-sv", this.SuppressIntermediateFileVersionMatching);
commandLineBuilder.AppendIfTrue("-sval", this.SuppressValidation);
commandLineBuilder.AppendSwitchIfNotNull("-usf ", this.UnreferencedSymbolsFile);
commandLineBuilder.AppendIfTrue("-xo", this.OutputAsXml);
commandLineBuilder.AppendSwitchIfNotNull("-contentsfile ", this.BindContentsFile);
commandLineBuilder.AppendSwitchIfNotNull("-outputsfile ", this.BindOutputsFile);
commandLineBuilder.AppendSwitchIfNotNull("-builtoutputsfile ", this.BindBuiltOutputsFile);
commandLineBuilder.AppendSwitchIfNotNull("-wixprojectfile ", this.WixProjectFile);
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
List<string> objectFilePaths = AdjustFilePaths(this.objectFiles, this.ReferencePaths);
commandLineBuilder.AppendFileNamesIfNotNull(objectFilePaths.ToArray(), " ");
}
}
}

Просмотреть файл

@ -0,0 +1,178 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task to run the WiX lib tool.
/// </summary>
public sealed class Lit : WixToolTask
{
private const string LitToolName = "lit.exe";
private string[] baseInputPaths;
private ITaskItem[] bindInputPaths;
private bool bindFiles;
private ITaskItem[] extensions;
private ITaskItem[] localizationFiles;
private ITaskItem[] objectFiles;
private ITaskItem outputFile;
private bool pedantic;
private bool suppressIntermediateFileVersionMatching;
private bool suppressSchemaValidation;
private string extensionDirectory;
private string[] referencePaths;
// TODO: remove this property entirely in v4.0
[Obsolete("Use BindInputPaths instead of BaseInputPaths.")]
public string[] BaseInputPaths
{
get { return this.baseInputPaths; }
set { this.baseInputPaths = value; }
}
public ITaskItem[] BindInputPaths
{
get { return this.bindInputPaths; }
set { this.bindInputPaths = value; }
}
public bool BindFiles
{
get { return this.bindFiles; }
set { this.bindFiles = value; }
}
public ITaskItem[] Extensions
{
get { return this.extensions; }
set { this.extensions = value; }
}
public ITaskItem[] LocalizationFiles
{
get { return this.localizationFiles; }
set { this.localizationFiles = value; }
}
[Required]
public ITaskItem[] ObjectFiles
{
get { return this.objectFiles; }
set { this.objectFiles = value; }
}
[Required]
[Output]
public ITaskItem OutputFile
{
get { return this.outputFile; }
set { this.outputFile = value; }
}
public bool Pedantic
{
get { return this.pedantic; }
set { this.pedantic = value; }
}
public bool SuppressIntermediateFileVersionMatching
{
get { return this.suppressIntermediateFileVersionMatching; }
set { this.suppressIntermediateFileVersionMatching = value; }
}
public bool SuppressSchemaValidation
{
get { return this.suppressSchemaValidation; }
set { this.suppressSchemaValidation = value; }
}
public string ExtensionDirectory
{
get { return this.extensionDirectory; }
set { this.extensionDirectory = value; }
}
public string[] ReferencePaths
{
get { return this.referencePaths; }
set { this.referencePaths = value; }
}
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of lit.exe</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return LitToolName; }
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply lit.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return LitToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), LitToolName);
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
base.BuildCommandLine(commandLineBuilder);
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendArrayIfNotNull("-b ", this.baseInputPaths);
if (null != this.BindInputPaths)
{
Queue<String> formattedBindInputPaths = new Queue<String>();
foreach (ITaskItem item in this.BindInputPaths)
{
String formattedPath = string.Empty;
String bindName = item.GetMetadata("BindName");
if (!String.IsNullOrEmpty(item.GetMetadata("BindName")))
{
formattedPath = String.Concat(bindName, "=", item.GetMetadata("FullPath"));
}
else
{
formattedPath = item.GetMetadata("FullPath");
}
formattedBindInputPaths.Enqueue(formattedPath);
}
commandLineBuilder.AppendArrayIfNotNull("-b ", formattedBindInputPaths.ToArray());
}
commandLineBuilder.AppendIfTrue("-bf", this.BindFiles);
commandLineBuilder.AppendExtensions(this.extensions, this.ExtensionDirectory, this.referencePaths);
commandLineBuilder.AppendArrayIfNotNull("-loc ", this.LocalizationFiles);
commandLineBuilder.AppendIfTrue("-pedantic", this.Pedantic);
commandLineBuilder.AppendIfTrue("-ss", this.SuppressSchemaValidation);
commandLineBuilder.AppendIfTrue("-sv", this.SuppressIntermediateFileVersionMatching);
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
List<string> objectFilePaths = AdjustFilePaths(this.objectFiles, this.ReferencePaths);
commandLineBuilder.AppendFileNamesIfNotNull(objectFilePaths.ToArray(), " ");
}
}
}

Просмотреть файл

@ -0,0 +1,140 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
/// <summary>
/// An MSBuild task to run the WiX patch builder.
/// </summary>
public sealed class Pyro : WixToolTask
{
private const string PyroToolName = "pyro.exe";
public bool BinaryDeltaPatch { get; set; }
public string CabinetCachePath { get; set; }
public string ExtensionDirectory { get; set; }
public ITaskItem[] Extensions { get; set; }
public bool LeaveTemporaryFiles { get; set; }
public string[] ReferencePaths { get; set; }
public bool ReuseCabinetCache { get; set; }
public bool SuppressAssemblies { get; set; }
public bool SuppressFiles { get; set; }
public bool SuppressFileHashAndInfo { get; set; }
public bool SuppressPdbOutput { get; set; }
[Required]
public string DefaultBaselineId { get; set; }
public ITaskItem[] BindInputPathsForTarget { get; set; }
public ITaskItem[] BindInputPathsForUpdated { get; set; }
[Required]
public ITaskItem InputFile { get; set; }
[Required]
[Output]
public ITaskItem OutputFile { get; set; }
[Output]
public ITaskItem PdbOutputFile { get; set; }
[Required]
public ITaskItem[] Transforms { get; set; }
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of pyro.exe.</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return PyroToolName; }
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply torch.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return PyroToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), PyroToolName);
}
/// <summary>
/// Builds a command line for bind-input paths (-bt and -bu switches).
/// </summary>
private void AppendBindInputPaths(WixCommandLineBuilder commandLineBuilder, IEnumerable<ITaskItem> bindInputPaths, string switchName)
{
if (null != bindInputPaths)
{
Queue<String> formattedBindInputPaths = new Queue<String>();
foreach (ITaskItem item in bindInputPaths)
{
String formattedPath = string.Empty;
String bindName = item.GetMetadata("BindName");
if (!String.IsNullOrEmpty(bindName))
{
formattedPath = String.Concat(bindName, "=", item.GetMetadata("FullPath"));
}
else
{
formattedPath = item.GetMetadata("FullPath");
}
formattedBindInputPaths.Enqueue(formattedPath);
}
commandLineBuilder.AppendArrayIfNotNull(switchName, formattedBindInputPaths.ToArray());
}
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
// Always put the output first so it is easy to find in the log.
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendSwitchIfNotNull("-pdbout ", this.PdbOutputFile);
base.BuildCommandLine(commandLineBuilder);
this.AppendBindInputPaths(commandLineBuilder, this.BindInputPathsForTarget, "-bt ");
this.AppendBindInputPaths(commandLineBuilder, this.BindInputPathsForUpdated, "-bu ");
commandLineBuilder.AppendFileNameIfNotNull(this.InputFile);
commandLineBuilder.AppendSwitchIfNotNull("-cc ", this.CabinetCachePath);
commandLineBuilder.AppendIfTrue("-delta", this.BinaryDeltaPatch);
commandLineBuilder.AppendExtensions(this.Extensions, this.ExtensionDirectory, this.ReferencePaths);
commandLineBuilder.AppendIfTrue("-notidy", this.LeaveTemporaryFiles);
commandLineBuilder.AppendIfTrue("-reusecab", this.ReuseCabinetCache);
commandLineBuilder.AppendIfTrue("-sa", this.SuppressAssemblies);
commandLineBuilder.AppendIfTrue("-sf", this.SuppressFiles);
commandLineBuilder.AppendIfTrue("-sh", this.SuppressFileHashAndInfo);
commandLineBuilder.AppendIfTrue("-spdb", this.SuppressPdbOutput);
foreach (ITaskItem transform in this.Transforms)
{
string transformPath = transform.ItemSpec;
string baselineId = transform.GetMetadata("OverrideBaselineId");
if (String.IsNullOrEmpty(baselineId))
{
baselineId = this.DefaultBaselineId;
}
commandLineBuilder.AppendTextIfNotNull(String.Format("-t {0} {1}", baselineId, transformPath));
}
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
}
}
}

Просмотреть файл

@ -0,0 +1,132 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// This task refreshes the generated file for bundle projects.
/// </summary>
public class RefreshBundleGeneratedFile : Task
{
private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled);
private static readonly Regex IllegalIdentifierCharacters = new Regex(@"[^A-Za-z0-9_\.]|\.{2,}", RegexOptions.Compiled); // non 'words' and assorted valid characters
private ITaskItem[] generatedFiles;
private ITaskItem[] projectReferencePaths;
/// <summary>
/// The list of files to generate.
/// </summary>
[Required]
public ITaskItem[] GeneratedFiles
{
get { return this.generatedFiles; }
set { this.generatedFiles = value; }
}
/// <summary>
/// All the project references in the project.
/// </summary>
[Required]
public ITaskItem[] ProjectReferencePaths
{
get { return this.projectReferencePaths; }
set { this.projectReferencePaths = value; }
}
/// <summary>
/// Gets a complete list of external cabs referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
ArrayList payloadGroupRefs = new ArrayList();
ArrayList packageGroupRefs = new ArrayList();
for (int i = 0; i < this.ProjectReferencePaths.Length; i++)
{
ITaskItem item = this.ProjectReferencePaths[i];
if (!String.IsNullOrEmpty(item.GetMetadata(Common.DoNotHarvest)))
{
continue;
}
string projectPath = CreateProjectReferenceDefineConstants.GetProjectPath(this.ProjectReferencePaths, i);
string projectName = Path.GetFileNameWithoutExtension(projectPath);
string referenceName = Common.GetIdentifierFromName(CreateProjectReferenceDefineConstants.GetReferenceName(item, projectName));
string[] pogs = item.GetMetadata("RefProjectOutputGroups").Split(';');
foreach (string pog in pogs)
{
if (!String.IsNullOrEmpty(pog))
{
// TODO: Add payload group references and package group references once heat is generating them
////payloadGroupRefs.Add(String.Format(CultureInfo.InvariantCulture, "{0}.{1}", referenceName, pog));
packageGroupRefs.Add(String.Format(CultureInfo.InvariantCulture, "{0}.{1}", referenceName, pog));
}
}
}
XmlDocument doc = new XmlDocument();
XmlProcessingInstruction head = doc.CreateProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
doc.AppendChild(head);
XmlElement rootElement = doc.CreateElement("Wix");
rootElement.SetAttribute("xmlns", "http://wixtoolset.org/schemas/v4/wxs");
doc.AppendChild(rootElement);
XmlElement fragment = doc.CreateElement("Fragment");
rootElement.AppendChild(fragment);
XmlElement payloadGroup = doc.CreateElement("PayloadGroup");
payloadGroup.SetAttribute("Id", "Bundle.Generated.Payloads");
fragment.AppendChild(payloadGroup);
XmlElement packageGroup = doc.CreateElement("PackageGroup");
packageGroup.SetAttribute("Id", "Bundle.Generated.Packages");
fragment.AppendChild(packageGroup);
foreach (string payloadGroupRef in payloadGroupRefs)
{
XmlElement payloadGroupRefElement = doc.CreateElement("PayloadGroupRef");
payloadGroupRefElement.SetAttribute("Id", payloadGroupRef);
payloadGroup.AppendChild(payloadGroupRefElement);
}
foreach (string packageGroupRef in packageGroupRefs)
{
XmlElement packageGroupRefElement = doc.CreateElement("PackageGroupRef");
packageGroupRefElement.SetAttribute("Id", packageGroupRef);
packageGroup.AppendChild(packageGroupRefElement);
}
foreach (ITaskItem item in this.GeneratedFiles)
{
string fullPath = item.GetMetadata("FullPath");
payloadGroup.SetAttribute("Id", Path.GetFileNameWithoutExtension(fullPath) + ".Payloads");
packageGroup.SetAttribute("Id", Path.GetFileNameWithoutExtension(fullPath) + ".Packages");
try
{
doc.Save(fullPath);
}
catch (Exception e)
{
// e.Message will be something like: "Access to the path 'fullPath' is denied."
this.Log.LogMessage(MessageImportance.High, "Unable to save generated file to '{0}'. {1}", fullPath, e.Message);
}
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,118 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// This task refreshes the generated file that contains ComponentGroupRefs
/// to harvested output.
/// </summary>
public class RefreshGeneratedFile : Task
{
private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled);
private static readonly Regex IllegalIdentifierCharacters = new Regex(@"[^A-Za-z0-9_\.]|\.{2,}", RegexOptions.Compiled); // non 'words' and assorted valid characters
private ITaskItem[] generatedFiles;
private ITaskItem[] projectReferencePaths;
/// <summary>
/// The list of files to generate.
/// </summary>
[Required]
public ITaskItem[] GeneratedFiles
{
get { return this.generatedFiles; }
set { this.generatedFiles = value; }
}
/// <summary>
/// All the project references in the project.
/// </summary>
[Required]
public ITaskItem[] ProjectReferencePaths
{
get { return this.projectReferencePaths; }
set { this.projectReferencePaths = value; }
}
/// <summary>
/// Gets a complete list of external cabs referenced by the given installer database file.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
ArrayList componentGroupRefs = new ArrayList();
for (int i = 0; i < this.ProjectReferencePaths.Length; i++)
{
ITaskItem item = this.ProjectReferencePaths[i];
if (!String.IsNullOrEmpty(item.GetMetadata(Common.DoNotHarvest)))
{
continue;
}
string projectPath = CreateProjectReferenceDefineConstants.GetProjectPath(this.ProjectReferencePaths, i);
string projectName = Path.GetFileNameWithoutExtension(projectPath);
string referenceName = Common.GetIdentifierFromName(CreateProjectReferenceDefineConstants.GetReferenceName(item, projectName));
string[] pogs = item.GetMetadata("RefProjectOutputGroups").Split(';');
foreach (string pog in pogs)
{
if (!String.IsNullOrEmpty(pog))
{
componentGroupRefs.Add(String.Format(CultureInfo.InvariantCulture, "{0}.{1}", referenceName, pog));
}
}
}
XmlDocument doc = new XmlDocument();
XmlProcessingInstruction head = doc.CreateProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
doc.AppendChild(head);
XmlElement rootElement = doc.CreateElement("Wix");
rootElement.SetAttribute("xmlns", "http://wixtoolset.org/schemas/v4/wxs");
doc.AppendChild(rootElement);
XmlElement fragment = doc.CreateElement("Fragment");
rootElement.AppendChild(fragment);
XmlElement componentGroup = doc.CreateElement("ComponentGroup");
componentGroup.SetAttribute("Id", "Product.Generated");
fragment.AppendChild(componentGroup);
foreach (string componentGroupRef in componentGroupRefs)
{
XmlElement componentGroupRefElement = doc.CreateElement("ComponentGroupRef");
componentGroupRefElement.SetAttribute("Id", componentGroupRef);
componentGroup.AppendChild(componentGroupRefElement);
}
foreach (ITaskItem item in this.GeneratedFiles)
{
string fullPath = item.GetMetadata("FullPath");
componentGroup.SetAttribute("Id", Path.GetFileNameWithoutExtension(fullPath));
try
{
doc.Save(fullPath);
}
catch (Exception e)
{
// e.Message will be something like: "Access to the path 'fullPath' is denied."
this.Log.LogMessage(MessageImportance.High, "Unable to save generated file to '{0}'. {1}", fullPath, e.Message);
}
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// Replaces occurances of OldValues with NewValues in String.
/// </summary>
public class ReplaceString : Task
{
/// <summary>
/// Text to operate on.
/// </summary>
[Output]
[Required]
public string Text { get; set; }
/// <summary>
/// List of old values to replace.
/// </summary>
[Required]
public string OldValue { get; set; }
/// <summary>
/// List of new values to replace old values with. If not specified, occurances of OldValue will be removed.
/// </summary>
public string NewValue { get; set; }
/// <summary>
/// Does the string replacement.
/// </summary>
/// <returns></returns>
public override bool Execute()
{
if (String.IsNullOrEmpty(this.Text))
{
return true;
}
if (String.IsNullOrEmpty(this.OldValue))
{
Log.LogError("OldValue must be specified");
return false;
}
this.Text = this.Text.Replace(this.OldValue, this.NewValue);
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,212 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.IO;
/// <summary>
/// This task searches for paths to references using the order specified in SearchPaths.
/// </summary>
public class ResolveWixReferences : Task
{
/// <summary>
/// Token value used in SearchPaths to indicate that the item's HintPath metadata should
/// be searched as a full file path to resolve the reference.
/// Must match wix.targets, case sensitive.
/// </summary>
private const string HintPathToken = "{HintPathFromItem}";
/// <summary>
/// Token value used in SearchPaths to indicate that the item's Identity should
/// be searched as a full file path to resolve the reference.
/// Must match wix.targets, case sensitive.
/// </summary>
private const string RawFileNameToken = "{RawFileName}";
/// <summary>
/// The list of references to resolve.
/// </summary>
[Required]
public ITaskItem[] WixReferences
{
get;
set;
}
/// <summary>
/// The directories or special locations that are searched to find the files
/// on disk that represent the references. The order in which the search paths are listed
/// is important. For each reference, the list of paths is searched from left to right.
/// When a file that represents the reference is found, that search stops and the search
/// for the next reference starts.
///
/// This parameter accepts the following types of values:
/// A directory path.
/// {HintPathFromItem}: Specifies that the task will examine the HintPath metadata
/// of the base item.
/// TODO : {CandidateAssemblyFiles}: Specifies that the task will examine the files
/// passed in through the CandidateAssemblyFiles parameter.
/// TODO : {Registry:_AssemblyFoldersBase_, _RuntimeVersion_, _AssemblyFoldersSuffix_}:
/// TODO : {AssemblyFolders}: Specifies the task will use the Visual Studio.NET 2003
/// finding-assemblies-from-registry scheme.
/// TODO : {GAC}: Specifies the task will search in the GAC.
/// {RawFileName}: Specifies the task will consider the Include value of the item to be
/// an exact path and file name.
/// </summary>
public string[] SearchPaths
{
get;
set;
}
/// <summary>
/// The filename extension(s) to be checked when searching.
/// </summary>
public string[] SearchFilenameExtensions
{
get;
set;
}
/// <summary>
/// Output items that contain the same metadata as input references and have been resolved to full paths.
/// </summary>
[Output]
public ITaskItem[] ResolvedWixReferences
{
get;
private set;
}
/// <summary>
/// Resolves reference paths by searching for referenced items using the specified SearchPaths.
/// </summary>
/// <returns>True on success, or throws an exception on failure.</returns>
public override bool Execute()
{
List<ITaskItem> resolvedReferences = new List<ITaskItem>();
foreach (ITaskItem reference in this.WixReferences)
{
ITaskItem resolvedReference = ResolveWixReferences.ResolveReference(reference, this.SearchPaths, this.SearchFilenameExtensions, this.Log);
this.Log.LogMessage(MessageImportance.Low, "Resolved path {0}", resolvedReference.ItemSpec);
resolvedReferences.Add(resolvedReference);
}
this.ResolvedWixReferences = resolvedReferences.ToArray();
return true;
}
/// <summary>
/// Resolves a single reference item by searcheing for referenced items using the specified SearchPaths.
/// This method is made public so the resolution logic can be reused by other tasks.
/// </summary>
/// <param name="reference">The referenced item.</param>
/// <param name="searchPaths">The paths to search.</param>
/// <param name="searchFilenameExtensions">Filename extensions to check.</param>
/// <param name="log">Logging helper.</param>
/// <returns>The resolved reference item, or the original reference if it could not be resolved.</returns>
public static ITaskItem ResolveReference(ITaskItem reference, string[] searchPaths, string[] searchFilenameExtensions, TaskLoggingHelper log)
{
if (reference == null)
{
throw new ArgumentNullException("reference");
}
if (searchPaths == null)
{
// Nothing to search, so just return the original reference item.
return reference;
}
if (searchFilenameExtensions == null)
{
searchFilenameExtensions = new string[] { };
}
// Copy all the metadata from the source
TaskItem resolvedReference = new TaskItem(reference);
log.LogMessage(MessageImportance.Low, "WixReference: {0}", reference.ItemSpec);
// Now find the resolved path based on our order of precedence
foreach (string searchPath in searchPaths)
{
log.LogMessage(MessageImportance.Low, "Trying {0}", searchPath);
if (searchPath.Equals(HintPathToken, StringComparison.Ordinal))
{
string path = reference.GetMetadata("HintPath");
log.LogMessage(MessageImportance.Low, "Trying path {0}", path);
if (File.Exists(path))
{
resolvedReference.ItemSpec = path;
break;
}
}
else if (searchPath.Equals(RawFileNameToken, StringComparison.Ordinal))
{
log.LogMessage(MessageImportance.Low, "Trying path {0}", resolvedReference.ItemSpec);
if (File.Exists(resolvedReference.ItemSpec))
{
break;
}
if (ResolveWixReferences.ResolveFilenameExtensions(resolvedReference,
resolvedReference.ItemSpec, searchFilenameExtensions, log))
{
break;
}
}
else
{
string path = Path.Combine(searchPath, Path.GetFileName(reference.ItemSpec));
log.LogMessage(MessageImportance.Low, "Trying path {0}", path);
if (File.Exists(path))
{
resolvedReference.ItemSpec = path;
break;
}
if (ResolveWixReferences.ResolveFilenameExtensions(resolvedReference,
path, searchFilenameExtensions, log))
{
break;
}
}
}
// Normalize the item path
resolvedReference.ItemSpec = resolvedReference.GetMetadata("FullPath");
return resolvedReference;
}
/// <summary>
/// Helper method for checking filename extensions when resolving references.
/// </summary>
/// <param name="reference">The reference being resolved.</param>
/// <param name="basePath">Full filename path without extension.</param>
/// <param name="filenameExtensions">Filename extensions to check.</param>
/// <param name="log">Logging helper.</param>
/// <returns>True if the item was resolved, else false.</returns>
private static bool ResolveFilenameExtensions(ITaskItem reference, string basePath, string[] filenameExtensions, TaskLoggingHelper log)
{
foreach (string filenameExtension in filenameExtensions)
{
string path = basePath + filenameExtension;
log.LogMessage(MessageImportance.Low, "Trying path {0}", path);
if (File.Exists(path))
{
reference.ItemSpec = path;
return true;
}
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
// 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.
namespace WixToolset.BuildTasks
{
using Microsoft.Build.Utilities;
public abstract class TaskBase : Task
{
public string ToolPath { get; set; }
public string AdditionalOptions { get; set; }
public bool RunAsSeparateProcess { get; set; }
/// <summary>
/// Gets or sets whether all warnings should be suppressed.
/// </summary>
public bool SuppressAllWarnings { get; set; }
/// <summary>
/// Gets or sets a list of specific warnings to be suppressed.
/// </summary>
public string[] SuppressSpecificWarnings { get; set; }
/// <summary>
/// Gets or sets whether all warnings should be treated as errors.
/// </summary>
public bool TreatWarningsAsErrors { get; set; }
/// <summary>
/// Gets or sets a list of specific warnings to treat as errors.
/// </summary>
public string[] TreatSpecificWarningsAsErrors { get; set; }
/// <summary>
/// Gets or sets whether to display verbose output.
/// </summary>
public bool VerboseOutput { get; set; }
/// <summary>
/// Gets or sets whether to display the logo.
/// </summary>
public bool NoLogo { get; set; }
public override bool Execute()
{
try
{
this.ExecuteCore();
}
catch (BuildException e)
{
this.Log.LogErrorFromException(e);
}
catch (Data.WixException e)
{
this.Log.LogErrorFromException(e);
}
return !this.Log.HasLoggedErrors;
}
protected abstract void ExecuteCore();
}
}

Просмотреть файл

@ -0,0 +1,159 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task to run the WiX transform generator.
/// </summary>
public sealed class Torch : WixToolTask
{
private const string TorchToolName = "Torch.exe";
private bool adminImage;
private ITaskItem baselineFile;
private string binaryExtractionPath;
private bool inputIsXml;
private bool leaveTemporaryFiles;
private bool outputAsXml;
private ITaskItem outputFile;
private bool preserveUnmodifiedContent;
private string suppressTransformErrorFlags;
private string transformValidationFlags;
private string transformValidationType;
private ITaskItem updateFile;
public bool AdminImage
{
get { return this.adminImage; }
set { this.adminImage = value; }
}
[Required]
public ITaskItem BaselineFile
{
get { return this.baselineFile; }
set { this.baselineFile = value; }
}
public string BinaryExtractionPath
{
get { return this.binaryExtractionPath; }
set { this.binaryExtractionPath = value; }
}
public bool LeaveTemporaryFiles
{
get { return this.leaveTemporaryFiles; }
set { this.leaveTemporaryFiles = value; }
}
public bool InputIsXml
{
get { return this.inputIsXml; }
set { this.inputIsXml = value; }
}
public bool OutputAsXml
{
get { return this.outputAsXml; }
set { this.outputAsXml = value; }
}
public bool PreserveUnmodifiedContent
{
get { return this.preserveUnmodifiedContent; }
set { this.preserveUnmodifiedContent = value; }
}
[Required]
[Output]
public ITaskItem OutputFile
{
get { return this.outputFile; }
set { this.outputFile = value; }
}
public string SuppressTransformErrorFlags
{
get { return this.suppressTransformErrorFlags; }
set { this.suppressTransformErrorFlags = value; }
}
public string TransformValidationType
{
get { return this.transformValidationType; }
set { this.transformValidationType = value; }
}
public string TransformValidationFlags
{
get { return this.transformValidationFlags; }
set { this.transformValidationFlags = value; }
}
[Required]
public ITaskItem UpdateFile
{
get { return this.updateFile; }
set { this.updateFile = value; }
}
/// <summary>
/// Get the name of the executable.
/// </summary>
/// <remarks>The ToolName is used with the ToolPath to get the location of torch.exe.</remarks>
/// <value>The name of the executable.</value>
protected override string ToolName
{
get { return TorchToolName; }
}
/// <summary>
/// Get the path to the executable.
/// </summary>
/// <remarks>GetFullPathToTool is only called when the ToolPath property is not set (see the ToolName remarks above).</remarks>
/// <returns>The full path to the executable or simply torch.exe if it's expected to be in the system path.</returns>
protected override string GenerateFullPathToTool()
{
// If there's not a ToolPath specified, it has to be in the system path.
if (String.IsNullOrEmpty(this.ToolPath))
{
return TorchToolName;
}
return Path.Combine(Path.GetFullPath(this.ToolPath), TorchToolName);
}
/// <summary>
/// Builds a command line from options in this task.
/// </summary>
protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
base.BuildCommandLine(commandLineBuilder);
commandLineBuilder.AppendIfTrue("-notidy", this.LeaveTemporaryFiles);
commandLineBuilder.AppendIfTrue("-xo", this.OutputAsXml);
commandLineBuilder.AppendIfTrue("-xi", this.InputIsXml);
commandLineBuilder.AppendIfTrue("-p", this.PreserveUnmodifiedContent);
commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions);
commandLineBuilder.AppendFileNameIfNotNull(this.BaselineFile);
commandLineBuilder.AppendFileNameIfNotNull(this.UpdateFile);
commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile);
commandLineBuilder.AppendIfTrue("-a", this.adminImage);
commandLineBuilder.AppendSwitchIfNotNull("-x ", this.BinaryExtractionPath);
commandLineBuilder.AppendSwitchIfNotNull("-serr ", this.SuppressTransformErrorFlags);
commandLineBuilder.AppendSwitchIfNotNull("-t ", this.TransformValidationType);
commandLineBuilder.AppendSwitchIfNotNull("-val ", this.TransformValidationFlags);
}
}
}

Просмотреть файл

@ -0,0 +1,229 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// This task assigns Culture metadata to files based on the value of the Culture attribute on the
/// WixLocalization element inside the file.
/// </summary>
public class WixAssignCulture : Task
{
private const string CultureAttributeName = "Culture";
private const string OutputFolderMetadataName = "OutputFolder";
private const string InvariantCultureIdentifier = "neutral";
private const string NullCultureIdentifier = "null";
/// <summary>
/// The list of cultures to build. Cultures are specified in the following form:
/// primary culture,first fallback culture, second fallback culture;...
/// Culture groups are seperated by semi-colons
/// Culture precedence within a culture group is evaluated from left to right where fallback cultures are
/// separated with commas.
/// The first (primary) culture in a culture group will be used as the output sub-folder.
/// </summary>
public string Cultures { get; set; }
/// <summary>
/// The list of files to apply culture information to.
/// </summary>
[Required]
public ITaskItem[] Files
{
get;
set;
}
/// <summary>
/// The files that had culture information applied
/// </summary>
[Output]
public ITaskItem[] CultureGroups
{
get;
private set;
}
/// <summary>
/// Applies culture information to the files specified by the Files property.
/// This task intentionally does not validate that strings are valid Cultures so that we can support
/// psuedo-loc.
/// </summary>
/// <returns>True upon completion of the task execution.</returns>
public override bool Execute()
{
// First, process the culture group list the user specified in the cultures property
List<CultureGroup> cultureGroups = new List<CultureGroup>();
if (!String.IsNullOrEmpty(this.Cultures))
{
// Get rid of extra quotes
this.Cultures = this.Cultures.Trim('\"');
foreach (string cultureGroupString in this.Cultures.Split(';'))
{
if (0 == cultureGroupString.Length)
{
// MSBuild v2.0.50727 cannnot handle "" items
// for the invariant culture we require the neutral keyword
continue;
}
CultureGroup cultureGroup = new CultureGroup(cultureGroupString);
cultureGroups.Add(cultureGroup);
}
}
else
{
// Only process the EmbeddedResource items if cultures was unspecified
foreach (ITaskItem file in this.Files)
{
// Ignore non-wxls
if (!String.Equals(file.GetMetadata("Extension"), ".wxl", StringComparison.OrdinalIgnoreCase))
{
Log.LogError("Unable to retrieve the culture for EmbeddedResource {0}. The file type is not supported.", file.ItemSpec);
return false;
}
XmlDocument wxlFile = new XmlDocument();
try
{
wxlFile.Load(file.ItemSpec);
}
catch (FileNotFoundException)
{
Log.LogError("Unable to retrieve the culture for EmbeddedResource {0}. The file was not found.", file.ItemSpec);
return false;
}
catch (Exception e)
{
Log.LogError("Unable to retrieve the culture for EmbeddedResource {0}: {1}", file.ItemSpec, e.Message);
return false;
}
// Take the culture value and try using it to create a culture.
XmlAttribute cultureAttr = wxlFile.DocumentElement.Attributes[WixAssignCulture.CultureAttributeName];
string wxlCulture = null == cultureAttr ? String.Empty : cultureAttr.Value;
if (0 == wxlCulture.Length)
{
// We use a keyword for the invariant culture because MSBuild v2.0.50727 cannnot handle "" items
wxlCulture = InvariantCultureIdentifier;
}
// We found the culture for the WXL, we now need to determine if it maps to a culture group specified
// in the Cultures property or if we need to create a new one.
Log.LogMessage(MessageImportance.Low, "Culture \"{0}\" from EmbeddedResource {1}.", wxlCulture, file.ItemSpec);
bool cultureGroupExists = false;
foreach (CultureGroup cultureGroup in cultureGroups)
{
foreach (string culture in cultureGroup.Cultures)
{
if (String.Equals(wxlCulture, culture, StringComparison.OrdinalIgnoreCase))
{
cultureGroupExists = true;
break;
}
}
}
// The WXL didn't match a culture group we already have so create a new one.
if (!cultureGroupExists)
{
cultureGroups.Add(new CultureGroup(wxlCulture));
}
}
}
// If we didn't create any culture groups the culture was unspecificed and no WXLs were included
// Build an unlocalized target in the output folder
if (cultureGroups.Count == 0)
{
cultureGroups.Add(new CultureGroup());
}
List<TaskItem> cultureGroupItems = new List<TaskItem>();
if (1 == cultureGroups.Count && 0 == this.Files.Length)
{
// Maintain old behavior, if only one culturegroup is specified and no WXL, output to the default folder
TaskItem cultureGroupItem = new TaskItem(cultureGroups[0].ToString());
cultureGroupItem.SetMetadata(OutputFolderMetadataName, CultureGroup.DefaultFolder);
cultureGroupItems.Add(cultureGroupItem);
}
else
{
foreach (CultureGroup cultureGroup in cultureGroups)
{
TaskItem cultureGroupItem = new TaskItem(cultureGroup.ToString());
cultureGroupItem.SetMetadata(OutputFolderMetadataName, cultureGroup.OutputFolder);
cultureGroupItems.Add(cultureGroupItem);
Log.LogMessage("Culture: {0}", cultureGroup.ToString());
}
}
this.CultureGroups = cultureGroupItems.ToArray();
return true;
}
private class CultureGroup
{
/// <summary>
/// TargetPath already has a '\', do not double it!
/// </summary>
public const string DefaultFolder = "";
/// <summary>
/// Initialize a null culture group
/// </summary>
public CultureGroup()
{
}
public CultureGroup(string cultureGroupString)
{
Debug.Assert(!String.IsNullOrEmpty(cultureGroupString));
foreach (string cultureString in cultureGroupString.Split(','))
{
this.Cultures.Add(cultureString);
}
}
public List<string> Cultures { get; } = new List<string>();
public string OutputFolder
{
get
{
string result = DefaultFolder;
if (this.Cultures.Count > 0 &&
!this.Cultures[0].Equals(InvariantCultureIdentifier, StringComparison.OrdinalIgnoreCase))
{
result = this.Cultures[0] + "\\";
}
return result;
}
}
public override string ToString()
{
if (this.Cultures.Count > 0)
{
return String.Join(";", this.Cultures);
}
// We use a keyword for a null culture because MSBuild cannnot handle "" items
// Null is different from neutral. For neutral we still want to do WXL
// filtering in Light.
return NullCultureIdentifier;
}
}
}
}

Просмотреть файл

@ -0,0 +1,177 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// Helper class for appending the command line arguments.
/// </summary>
public class WixCommandLineBuilder : CommandLineBuilder
{
internal const int Unspecified = -1;
/// <summary>
/// Append a switch to the command line if the value has been specified.
/// </summary>
/// <param name="switchName">Switch to append.</param>
/// <param name="value">Value specified by the user.</param>
public void AppendIfSpecified(string switchName, int value)
{
if (value != Unspecified)
{
this.AppendSwitchIfNotNull(switchName, value.ToString(CultureInfo.InvariantCulture));
}
}
/// <summary>
/// Append a switch to the command line if the condition is true.
/// </summary>
/// <param name="switchName">Switch to append.</param>
/// <param name="condition">Condition specified by the user.</param>
public void AppendIfTrue(string switchName, bool condition)
{
if (condition)
{
this.AppendSwitch(switchName);
}
}
/// <summary>
/// Append a switch to the command line if any values in the array have been specified.
/// </summary>
/// <param name="switchName">Switch to append.</param>
/// <param name="values">Values specified by the user.</param>
public void AppendArrayIfNotNull(string switchName, IEnumerable<ITaskItem> values)
{
if (values != null)
{
foreach (ITaskItem value in values)
{
this.AppendSwitchIfNotNull(switchName, value);
}
}
}
/// <summary>
/// Append a switch to the command line if any values in the array have been specified.
/// </summary>
/// <param name="switchName">Switch to append.</param>
/// <param name="values">Values specified by the user.</param>
public void AppendArrayIfNotNull(string switchName, IEnumerable<string> values)
{
if (values != null)
{
foreach (string value in values)
{
this.AppendSwitchIfNotNull(switchName, value);
}
}
}
/// <summary>
/// Build the extensions argument. Each extension is searched in the current folder, user defined search
/// directories (ReferencePath), HintPath, and under Wix Extension Directory in that order.
/// The order of precedence is based off of that described in Microsoft.Common.Targets's SearchPaths
/// property for the ResolveAssemblyReferences task.
/// </summary>
/// <param name="extensions">The list of extensions to include.</param>
/// <param name="wixExtensionDirectory">Evaluated default folder for Wix Extensions</param>
/// <param name="referencePaths">User defined reference directories to search in</param>
public void AppendExtensions(ITaskItem[] extensions, string wixExtensionDirectory, string [] referencePaths)
{
if (extensions == null)
{
return;
}
foreach (ITaskItem extension in extensions)
{
string className = extension.GetMetadata("Class");
string fileName = Path.GetFileName(extension.ItemSpec);
if (String.IsNullOrEmpty(Path.GetExtension(fileName)))
{
fileName += ".dll";
}
// First try reference paths
var resolvedPath = FileSearchHelperMethods.SearchFilePaths(referencePaths, fileName);
if (String.IsNullOrEmpty(resolvedPath))
{
// Now try HintPath
resolvedPath = extension.GetMetadata("HintPath");
if (!File.Exists(resolvedPath))
{
// Now try the item itself
resolvedPath = extension.ItemSpec;
if (String.IsNullOrEmpty(Path.GetExtension(resolvedPath)))
{
resolvedPath += ".dll";
}
if (!File.Exists(resolvedPath))
{
if (!String.IsNullOrEmpty(wixExtensionDirectory))
{
// Now try the extension directory
resolvedPath = Path.Combine(wixExtensionDirectory, Path.GetFileName(resolvedPath));
}
if (!File.Exists(resolvedPath))
{
// Extension wasn't found, just set it to the extension name passed in
resolvedPath = extension.ItemSpec;
}
}
}
}
if (String.IsNullOrEmpty(className))
{
this.AppendSwitchIfNotNull("-ext ", resolvedPath);
}
else
{
this.AppendSwitchIfNotNull("-ext ", className + ", " + resolvedPath);
}
}
}
/// <summary>
/// Append arbitrary text to the command-line if specified.
/// </summary>
/// <param name="textToAppend">Text to append.</param>
public void AppendTextIfNotNull(string textToAppend)
{
if (!String.IsNullOrEmpty(textToAppend))
{
this.AppendSpaceIfNotEmpty();
this.AppendTextUnquoted(textToAppend);
}
}
/// <summary>
/// Append arbitrary text to the command-line if specified.
/// </summary>
/// <param name="textToAppend">Text to append.</param>
public void AppendTextIfNotWhitespace(string textToAppend)
{
if (!String.IsNullOrWhiteSpace(textToAppend))
{
this.AppendSpaceIfNotEmpty();
this.AppendTextUnquoted(textToAppend);
}
}
}
}

Просмотреть файл

@ -0,0 +1,403 @@
// 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.
namespace WixToolset.BuildTasks
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using WixToolset.Core.CommandLine;
/// <summary>
/// Base class for WiX tool tasks; executes tools in-process
/// so that repeated invocations are much faster.
/// </summary>
public abstract class WixToolTask : ToolTask, IDisposable
{
private string additionalOptions;
private bool disposed;
private bool noLogo;
private bool runAsSeparateProcess;
private bool suppressAllWarnings;
private string[] suppressSpecificWarnings;
private string[] treatSpecificWarningsAsErrors;
private bool treatWarningsAsErrors;
private bool verboseOutput;
private Queue<string> messageQueue;
private ManualResetEvent messagesAvailable;
private ManualResetEvent toolExited;
private int exitCode;
/// <summary>
/// Gets or sets additional options that are appended the the tool command-line.
/// </summary>
/// <remarks>
/// This allows the task to support extended options in the tool which are not
/// explicitly implemented as properties on the task.
/// </remarks>
public string AdditionalOptions
{
get { return this.additionalOptions; }
set { this.additionalOptions = value; }
}
/// <summary>
/// Gets or sets a flag indicating whether the task should be run as separate
/// process instead of in-proc with MSBuild which is the default.
/// </summary>
public bool RunAsSeparateProcess
{
get { return this.runAsSeparateProcess; }
set { this.runAsSeparateProcess = value; }
}
#region Common Options
/// <summary>
/// Gets or sets whether all warnings should be suppressed.
/// </summary>
public bool SuppressAllWarnings
{
get { return this.suppressAllWarnings; }
set { this.suppressAllWarnings = value; }
}
/// <summary>
/// Gets or sets a list of specific warnings to be suppressed.
/// </summary>
public string[] SuppressSpecificWarnings
{
get { return this.suppressSpecificWarnings; }
set { this.suppressSpecificWarnings = value; }
}
/// <summary>
/// Gets or sets whether all warnings should be treated as errors.
/// </summary>
public bool TreatWarningsAsErrors
{
get { return this.treatWarningsAsErrors; }
set { this.treatWarningsAsErrors = value; }
}
/// <summary>
/// Gets or sets a list of specific warnings to treat as errors.
/// </summary>
public string[] TreatSpecificWarningsAsErrors
{
get { return this.treatSpecificWarningsAsErrors; }
set { this.treatSpecificWarningsAsErrors = value; }
}
/// <summary>
/// Gets or sets whether to display verbose output.
/// </summary>
public bool VerboseOutput
{
get { return this.verboseOutput; }
set { this.verboseOutput = value; }
}
/// <summary>
/// Gets or sets whether to display the logo.
/// </summary>
public bool NoLogo
{
get { return this.noLogo; }
set { this.noLogo = value; }
}
#endregion
/// <summary>
/// Cleans up the ManualResetEvent members
/// </summary>
public void Dispose()
{
if (!this.disposed)
{
this.Dispose(true);
GC.SuppressFinalize(this);
disposed = true;
}
}
/// <summary>
/// Cleans up the ManualResetEvent members
/// </summary>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
messagesAvailable.Close();
toolExited.Close();
}
}
/// <summary>
/// Generate the command line arguments to write to the response file from the properties.
/// </summary>
/// <returns>Command line string.</returns>
protected override string GenerateResponseFileCommands()
{
WixCommandLineBuilder commandLineBuilder = new WixCommandLineBuilder();
this.BuildCommandLine(commandLineBuilder);
return commandLineBuilder.ToString();
}
/// <summary>
/// Builds a command line from options in this and derivative tasks.
/// </summary>
/// <remarks>
/// Derivative classes should call BuildCommandLine() on the base class to ensure that common command line options are added to the command.
/// </remarks>
protected virtual void BuildCommandLine(WixCommandLineBuilder commandLineBuilder)
{
commandLineBuilder.AppendIfTrue("-nologo", this.NoLogo);
commandLineBuilder.AppendArrayIfNotNull("-sw", this.SuppressSpecificWarnings);
commandLineBuilder.AppendIfTrue("-sw", this.SuppressAllWarnings);
commandLineBuilder.AppendIfTrue("-v", this.VerboseOutput);
commandLineBuilder.AppendArrayIfNotNull("-wx", this.TreatSpecificWarningsAsErrors);
commandLineBuilder.AppendIfTrue("-wx", this.TreatWarningsAsErrors);
}
/// <summary>
/// Executes a tool in-process by loading the tool assembly and invoking its entrypoint.
/// </summary>
/// <param name="pathToTool">Path to the tool to be executed; must be a managed executable.</param>
/// <param name="responseFileCommands">Commands to be written to a response file.</param>
/// <param name="commandLineCommands">Commands to be passed directly on the command-line.</param>
/// <returns>The tool exit code.</returns>
protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
if (this.RunAsSeparateProcess)
{
return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
this.messageQueue = new Queue<string>();
this.messagesAvailable = new ManualResetEvent(false);
this.toolExited = new ManualResetEvent(false);
WixToolTaskLogger logger = new WixToolTaskLogger(this.messageQueue, this.messagesAvailable);
TextWriter saveConsoleOut = Console.Out;
TextWriter saveConsoleError = Console.Error;
Console.SetOut(logger);
Console.SetError(logger);
string responseFile = null;
try
{
responseFile = this.GetTemporaryResponseFile(responseFileCommands, out var responseFileSwitch);
if (!String.IsNullOrEmpty(responseFileSwitch))
{
commandLineCommands = commandLineCommands + " " + responseFileSwitch;
}
string[] arguments = CommandLineResponseFile.ParseArgumentsToArray(commandLineCommands);
Thread toolThread = new Thread(new ParameterizedThreadStart(this.ExecuteToolThread));
toolThread.Start(new object[] { pathToTool, arguments });
this.HandleToolMessages();
if (this.exitCode == 0 && this.Log.HasLoggedErrors)
{
this.exitCode = -1;
}
return this.exitCode;
}
finally
{
if (responseFile != null)
{
File.Delete(responseFile);
}
Console.SetOut(saveConsoleOut);
Console.SetError(saveConsoleError);
}
}
/// <summary>
/// Called by a new thread to execute the tool in that thread.
/// </summary>
/// <param name="parameters">Tool path and arguments array.</param>
private void ExecuteToolThread(object parameters)
{
try
{
object[] pathAndArguments = (object[])parameters;
Assembly toolAssembly = Assembly.LoadFrom((string)pathAndArguments[0]);
this.exitCode = (int)toolAssembly.EntryPoint.Invoke(null, new object[] { pathAndArguments[1] });
}
catch (FileNotFoundException fnfe)
{
Log.LogError("Unable to load tool from path {0}. Consider setting the ToolPath parameter to $(WixToolPath).", fnfe.FileName);
this.exitCode = -1;
}
catch (Exception ex)
{
this.exitCode = -1;
this.LogEventsFromTextOutput(ex.Message, MessageImportance.High);
foreach (string stackTraceLine in ex.StackTrace.Split('\n'))
{
this.LogEventsFromTextOutput(stackTraceLine.TrimEnd(), MessageImportance.High);
}
throw;
}
finally
{
this.toolExited.Set();
}
}
/// <summary>
/// Waits for messages from the tool thread and sends them to the MSBuild logger on the original thread.
/// Returns when the tool thread exits.
/// </summary>
private void HandleToolMessages()
{
WaitHandle[] waitHandles = new WaitHandle[] { this.messagesAvailable, this.toolExited };
while (WaitHandle.WaitAny(waitHandles) == 0)
{
lock (this.messageQueue)
{
while (this.messageQueue.Count > 0)
{
this.LogEventsFromTextOutput(messageQueue.Dequeue(), MessageImportance.Normal);
}
this.messagesAvailable.Reset();
}
}
}
/// <summary>
/// Creates a temporary response file for tool execution.
/// </summary>
/// <returns>Path to the response file.</returns>
/// <remarks>
/// The temporary file should be deleted after the tool execution is finished.
/// </remarks>
private string GetTemporaryResponseFile(string responseFileCommands, out string responseFileSwitch)
{
string responseFile = null;
responseFileSwitch = null;
if (!String.IsNullOrEmpty(responseFileCommands))
{
responseFile = Path.GetTempFileName();
using (StreamWriter writer = new StreamWriter(responseFile, false, this.ResponseFileEncoding))
{
writer.Write(responseFileCommands);
}
responseFileSwitch = this.GetResponseFileSwitch(responseFile);
}
return responseFile;
}
/// <summary>
/// Cycles thru each task to find correct path of the file in question.
/// Looks at item spec, hintpath and then in user defined Reference Paths
/// </summary>
/// <param name="tasks">Input task array</param>
/// <param name="referencePaths">SemiColon delimited directories to search</param>
/// <returns>List of task item file paths</returns>
[SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
protected static List<string> AdjustFilePaths(ITaskItem[] tasks, string[] referencePaths)
{
List<string> sourceFilePaths = new List<string>();
if (tasks == null)
{
return sourceFilePaths;
}
foreach (ITaskItem task in tasks)
{
string filePath = task.ItemSpec;
if (!File.Exists(filePath))
{
filePath = task.GetMetadata("HintPath");
if (!File.Exists(filePath))
{
string searchPath = FileSearchHelperMethods.SearchFilePaths(referencePaths, filePath);
if (!String.IsNullOrEmpty(searchPath))
{
filePath = searchPath;
}
}
}
sourceFilePaths.Add(filePath);
}
return sourceFilePaths;
}
/// <summary>
/// Used as a replacement for Console.Out to capture output from a tool
/// and redirect it to the MSBuild logging system.
/// </summary>
private class WixToolTaskLogger : TextWriter
{
private StringBuilder buffer;
private Queue<string> messageQueue;
private ManualResetEvent messagesAvailable;
/// <summary>
/// Creates a new logger that sends tool output to the tool task's log handler.
/// </summary>
public WixToolTaskLogger(Queue<string> messageQueue, ManualResetEvent messagesAvailable) : base(CultureInfo.CurrentCulture)
{
this.messageQueue = messageQueue;
this.messagesAvailable = messagesAvailable;
this.buffer = new StringBuilder();
}
/// <summary>
/// Gets the encoding of the logger.
/// </summary>
public override Encoding Encoding
{
get { return Encoding.Unicode; }
}
/// <summary>
/// Redirects output to a buffer; watches for newlines and sends each line to the
/// MSBuild logging system.
/// </summary>
/// <param name="value">Character being written.</param>
/// <remarks>All other Write() variants eventually call into this one.</remarks>
public override void Write(char value)
{
lock (this.messageQueue)
{
if (value == '\n')
{
if (this.buffer.Length > 0 && this.buffer[this.buffer.Length - 1] == '\r')
{
this.buffer.Length = this.buffer.Length - 1;
}
this.messageQueue.Enqueue(this.buffer.ToString());
this.messagesAvailable.Set();
this.buffer.Length = 0;
}
else
{
this.buffer.Append(value);
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.1</TargetFrameworks>
<Description></Description>
<Title>WiX Toolset MSBuild Tasks</Title>
<DebugType>embedded</DebugType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
</PropertyGroup>
<PropertyGroup>
<NoWarn>NU1701</NoWarn>
</PropertyGroup>
<PropertyGroup>
<!-- <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> -->
</PropertyGroup>
<ItemGroup>
<Content Include="redirects\wix.targets" CopyToOutputDirectory="PreserveNewest" />
<Content Include="redirects\wix.ca.targets" CopyToOutputDirectory="PreserveNewest" />
<Content Include="wix.targets" CopyToOutputDirectory="PreserveNewest" />
<Content Include="wix.ca.targets" CopyToOutputDirectory="PreserveNewest" />
<Content Include="wix.harvest.targets" CopyToOutputDirectory="PreserveNewest" />
<Content Include="wix.signing.targets" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(WixToolsetRootFolder)\Core\src\WixToolset.Core\WixToolset.Core.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<PackageReference Include="WixToolset.Core" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<ProjectReference Include="$(WixToolsetRootFolder)\Core\src\WixToolset.Core.Burn\WixToolset.Core.Burn.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<ProjectReference Include="$(WixToolsetRootFolder)\Core\src\WixToolset.Core.WindowsInstaller\WixToolset.Core.WindowsInstaller.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Core\README.md') " />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="14.3" Condition="'$(TargetFramework)'=='net461' " />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.3.409" Condition="'$(TargetFramework)'=='netcoreapp2.1' " />
<PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="4.0.*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63102-01" PrivateAssets="All"/>
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<WixInstallFolder>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\WiX Toolset\v4', 'InstallFolder', null, RegistryView.Registry32))</WixInstallFolder>
</PropertyGroup>
<Import Project="$(WixInstallFolder)sdk\wix.ca.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<WixInstallFolder>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\WiX Toolset\v4', 'InstallFolder', null, RegistryView.Registry32))</WixInstallFolder>
</PropertyGroup>
<Import Project="$(WixInstallFolder)bin\wix.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(CustomBeforeWixCATargets)" Condition=" '$(CustomBeforeWixCATargets)' != '' and Exists('$(CustomBeforeWixCATargets)')" />
<PropertyGroup>
<WixCATargetsImported>true</WixCATargetsImported>
<TargetCAFileName Condition=" '$(TargetCAFileName)' == '' ">$(TargetName).CA$(TargetExt)</TargetCAFileName>
<WixSdkPath Condition=" '$(WixSdkPath)' == '' ">$(MSBuildThisFileDirectory)</WixSdkPath>
<WixSdkX86Path Condition=" '$(WixSdkX86Path)' == '' ">$(WixSdkPath)x86\</WixSdkX86Path>
<WixSdkX64Path Condition=" '$(WixSdkX64Path)' == '' ">$(WixSdkPath)x64\</WixSdkX64Path>
<MakeSfxCA Condition=" '$(MakeSfxCA)' == '' ">$(WixSdkPath)MakeSfxCA.exe</MakeSfxCA>
<SfxCADll Condition=" '$(SfxCADll)' == '' and '$(Platform)' == 'x64' ">$(WixSdkX64Path)SfxCA.dll</SfxCADll>
<SfxCADll Condition=" '$(SfxCADll)' == '' ">$(WixSdkX86Path)SfxCA.dll</SfxCADll>
</PropertyGroup>
<!--
==================================================================================================
PackCustomAction
Creates an MSI managed custom action package that includes the custom action assembly,
local assembly dependencies, and project content files.
[IN]
@(IntermediateAssembly) - Managed custom action assembly.
@(Content) - Project items of type Content will be included in the package.
$(CustomActionContents) - Optional space-delimited list of additional files to include.
[OUT]
$(IntermediateOutputPath)$(TargetCAFileName) - Managed custom action package with unmanaged stub.
==================================================================================================
-->
<Target Name="PackCustomAction"
Inputs="@(IntermediateAssembly);@(Content);$(CustomActionContents)"
Outputs="$(IntermediateOutputPath)$(TargetCAFileName)">
<!-- Find all referenced items marked CopyLocal, but exclude non-binary files. -->
<ItemGroup>
<CustomActionReferenceContents Include="@(ReferenceCopyLocalPaths)"
Condition=" '%(Extension)' == '.dll' or '%(Extension)' == '.exe' " />
<CustomActionReferenceContents Include="@(ReferenceComWrappersToCopyLocal)"
Condition=" '%(Extension)' == '.dll' or '%(Extension)' == '.exe' " />
<!-- include PDBs for Debug only -->
<CustomActionReferenceContents Include="@(IntermediateAssembly->'%(RootDir)%(Directory)%(Filename).pdb')"
Condition=" Exists('%(RootDir)%(Directory)%(Filename).pdb') and '$(Configuration)' == 'Debug' " />
<CustomActionReferenceContents Include="@(ReferenceCopyLocalPaths)"
Condition=" '%(Extension)' == '.pdb' and '$(Configuration)' == 'Debug' " />
<CustomActionReferenceContents Include="@(ReferenceComWrappersToCopyLocal)"
Condition=" '%(Extension)' == '.pdb' and '$(Configuration)' == 'Debug' " />
</ItemGroup>
<!--
Items to include in the CA package:
- Reference assemblies marked CopyLocal
- Project items of type Content
- Additional items in the CustomActionContents property
-->
<PropertyGroup>
<CustomActionContents>@(CustomActionReferenceContents);@(Content->'%(FullPath)');$(CustomActionContents)</CustomActionContents>
</PropertyGroup>
<ItemGroup>
<IntermediateCAAssembly Include="@(IntermediateAssembly->'%(FullPath)')" />
<IntermediateCAPackage Include="@(IntermediateAssembly->'%(RootDir)%(Directory)$(TargetCAFileName)')" />
</ItemGroup>
<!-- Run the MakeSfxCA.exe CA packaging tool. -->
<Exec Command='"$(MakeSfxCA)" "@(IntermediateCAPackage)" "$(SfxCADll)" "@(IntermediateCAAssembly)" "$(CustomActionContents)"'
WorkingDirectory="$(ProjectDir)" />
<!-- Add modules to be copied to output dir. -->
<ItemGroup>
<AddModules Include="@(IntermediateCAPackage)" />
</ItemGroup>
</Target>
<!--
==================================================================================================
CleanCustomAction
Cleans the .CA.dll binary created by the PackCustomAction target.
==================================================================================================
-->
<Target Name="CleanCustomAction">
<Delete Files="$(IntermediateOutputPath)$(TargetCAFileName)"
TreatErrorsAsWarnings="true" />
</Target>
<!--
==================================================================================================
AfterCompile (redefinition)
Calls the PackCustomAction target after compiling.
Overrides the empty AfterCompile target from Microsoft.Common.targets.
==================================================================================================
-->
<Target Name="AfterCompile"
DependsOnTargets="PackCustomAction" />
<!--
==================================================================================================
BeforeClean (redefinition)
Calls the CleanCustomAction target before cleaning.
Overrides the empty AfterCompile target from Microsoft.Common.targets.
==================================================================================================
-->
<Target Name="BeforeClean"
DependsOnTargets="CleanCustomAction" />
<Import Project="$(CustomAfterWixCATargets)" Condition=" '$(CustomAfterWixCATargets)' != '' and Exists('$(CustomAfterWixCATargets)')" />
</Project>

Просмотреть файл

@ -0,0 +1,511 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- These properties can be overridden to support non-default installations. -->
<PropertyGroup>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildThisFileFullPath)</WixTargetsPath>
<WixTasksPath Condition=" '$(WixTasksPath)' == '' ">$(WixTargetsPath)WixTasks.dll</WixTasksPath>
</PropertyGroup>
<!-- These tasks are extensions for harvesting WiX source code from other sources. -->
<UsingTask TaskName="HeatFile" AssemblyFile="$(WixTasksPath)" />
<UsingTask TaskName="HeatDirectory" AssemblyFile="$(WixTasksPath)" />
<UsingTask TaskName="HeatProject" AssemblyFile="$(WixTasksPath)" />
<UsingTask TaskName="RefreshGeneratedFile" AssemblyFile="$(WixTasksPath)"/>
<UsingTask TaskName="RefreshBundleGeneratedFile" AssemblyFile="$(WixTasksPath)"/>
<!-- Default Harvester properties-->
<PropertyGroup>
<HarvestNoLogo Condition=" '$(HarvestNoLogo)' == '' ">$(NoLogo)</HarvestNoLogo>
<HarvestSuppressAllWarnings Condition=" '$(HarvestSuppressAllWarnings)' == '' ">$(SuppressAllWarnings)</HarvestSuppressAllWarnings>
<HarvestSuppressSpecificWarnings Condition=" '$(HarvestSuppressSpecificWarnings)' == '' ">$(SuppressSpecificWarnings)</HarvestSuppressSpecificWarnings>
<HarvestTreatWarningsAsErrors Condition=" '$(HarvestTreatWarningsAsErrors)' == '' ">$(TreatWarningsAsErrors)</HarvestTreatWarningsAsErrors>
<HarvestTreatSpecificWarningsAsErrors Condition=" '$(HarvestTreatSpecificWarningsAsErrors)' == '' ">$(TreatSpecificWarningsAsErrors)</HarvestTreatSpecificWarningsAsErrors>
<HarvestVerboseOutput Condition=" '$(HarvestVerboseOutput)' == '' ">$(VerboseOutput)</HarvestVerboseOutput>
<HarvestAutogenerateGuids Condition=" '$(HarvestAutogenerateGuids)' == '' ">true</HarvestAutogenerateGuids>
<HarvestGenerateGuidsNow Condition=" '$(HarvestGenerateGuidsNow)' == '' ">false</HarvestGenerateGuidsNow>
<HarvestSuppressFragments Condition=" '$(HarvestSuppressFragments)' == '' ">true</HarvestSuppressFragments>
<HarvestSuppressUniqueIds Condition=" '$(HarvestSuppressUniqueIds)' == '' ">false</HarvestSuppressUniqueIds>
</PropertyGroup>
<!-- Default HarvestProjects properties -->
<PropertyGroup>
<!-- Project harvesting is defaulted to off until it works more consistently. -->
<EnableProjectHarvesting Condition=" '$(EnableProjectHarvesting)'=='' ">false</EnableProjectHarvesting>
<HarvestProjectsNoLogo Condition=" '$(HarvestProjectsNoLogo)' == '' ">$(HarvestNoLogo)</HarvestProjectsNoLogo>
<HarvestProjectsSuppressAllWarnings Condition=" '$(HarvestProjectsSuppressAllWarnings)' == '' ">$(HarvestSuppressAllWarnings)</HarvestProjectsSuppressAllWarnings>
<HarvestProjectsSuppressSpecificWarnings Condition=" '$(HarvestProjectsSuppressSpecificWarnings)' == '' ">$(HarvestSuppressSpecificWarnings)</HarvestProjectsSuppressSpecificWarnings>
<HarvestProjectsTreatWarningsAsErrors Condition=" '$(HarvestProjectsTreatWarningsAsErrors)' == '' ">$(HarvestTreatWarningsAsErrors)</HarvestProjectsTreatWarningsAsErrors>
<HarvestProjectsTreatSpecificWarningsAsErrors Condition=" '$(HarvestProjectsTreatSpecificWarningsAsErrors)' == '' ">$(HarvestTreatSpecificWarningsAsErrors)</HarvestProjectsTreatSpecificWarningsAsErrors>
<HarvestProjectsVerboseOutput Condition=" '$(HarvestProjectsVerboseOutput)' == '' ">$(HarvestVerboseOutput)</HarvestProjectsVerboseOutput>
<HarvestProjectsAutogenerateGuids Condition=" '$(HarvestProjectsAutogenerateGuids)' == '' ">$(HarvestAutogenerateGuids)</HarvestProjectsAutogenerateGuids>
<HarvestProjectsGenerateGuidsNow Condition=" '$(HarvestProjectsGenerateGuidsNow)' == '' ">$(HarvestGenerateGuidsNow)</HarvestProjectsGenerateGuidsNow>
<HarvestProjectsSuppressFragments Condition=" '$(HarvestProjectsSuppressFragments)' == '' ">$(HarvestSuppressFragments)</HarvestProjectsSuppressFragments>
<HarvestProjectsSuppressUniqueIds Condition=" '$(HarvestProjectsSuppressUniqueIds)' == '' ">$(HarvestSuppressUniqueIds)</HarvestProjectsSuppressUniqueIds>
<HarvestProjectsTransforms Condition=" '$(HarvestProjectsTransforms)' == '' ">$(HarvestTransforms)</HarvestProjectsTransforms>
<HarvestProjectsGeneratedFile Condition=" '$(HarvestProjectsGeneratedFile)' == '' and '$(OutputType)' != 'Bundle' ">$(IntermediateOutputPath)Product.Generated.wxs</HarvestProjectsGeneratedFile>
<HarvestProjectsGeneratedFile Condition=" '$(HarvestProjectsGeneratedFile)' == '' and '$(OutputType)' == 'Bundle' ">$(IntermediateOutputPath)Bundle.Generated.wxs</HarvestProjectsGeneratedFile>
</PropertyGroup>
<!-- Default HarvestDirectory properties -->
<PropertyGroup>
<HarvestDirectoryNoLogo Condition=" '$(HarvestDirectoryNoLogo)' == '' ">$(HarvestNoLogo)</HarvestDirectoryNoLogo>
<HarvestDirectorySuppressAllWarnings Condition=" '$(HarvestDirectorySuppressAllWarnings)' == '' ">$(HarvestSuppressAllWarnings)</HarvestDirectorySuppressAllWarnings>
<HarvestDirectorySuppressSpecificWarnings Condition=" '$(HarvestDirectorySuppressSpecificWarnings)' == '' ">$(HarvestSuppressSpecificWarnings)</HarvestDirectorySuppressSpecificWarnings>
<HarvestDirectoryTreatWarningsAsErrors Condition=" '$(HarvestDirectoryTreatWarningsAsErrors)' == '' ">$(HarvestTreatWarningsAsErrors)</HarvestDirectoryTreatWarningsAsErrors>
<HarvestDirectoryTreatSpecificWarningsAsErrors Condition=" '$(HarvestDirectoryTreatSpecificWarningsAsErrors)' == '' ">$(HarvestTreatSpecificWarningsAsErrors)</HarvestDirectoryTreatSpecificWarningsAsErrors>
<HarvestDirectoryVerboseOutput Condition=" '$(HarvestDirectoryVerboseOutput)' == '' ">$(HarvestVerboseOutput)</HarvestDirectoryVerboseOutput>
<HarvestDirectoryAutogenerateGuids Condition=" '$(HarvestDirectoryAutogenerateGuids)' == '' ">$(HarvestAutogenerateGuids)</HarvestDirectoryAutogenerateGuids>
<HarvestDirectoryGenerateGuidsNow Condition=" '$(HarvestDirectoryGenerateGuidsNow)' == '' ">$(HarvestGenerateGuidsNow)</HarvestDirectoryGenerateGuidsNow>
<HarvestDirectorySuppressFragments Condition=" '$(HarvestDirectorySuppressFragments)' == '' ">$(HarvestSuppressFragments)</HarvestDirectorySuppressFragments>
<HarvestDirectorySuppressUniqueIds Condition=" '$(HarvestDirectorySuppressUniqueIds)' == '' ">$(HarvestSuppressUniqueIds)</HarvestDirectorySuppressUniqueIds>
<HarvestDirectoryTransforms Condition=" '$(HarvestDirectoryTransforms)' == '' ">$(HarvestTransforms)</HarvestDirectoryTransforms>
</PropertyGroup>
<!-- Default HarvestFile properties -->
<PropertyGroup>
<HarvestFileNoLogo Condition=" '$(HarvestFileNoLogo)' == '' ">$(HarvestNoLogo)</HarvestFileNoLogo>
<HarvestFileSuppressAllWarnings Condition=" '$(HarvestFileSuppressAllWarnings)' == '' ">$(HarvestSuppressAllWarnings)</HarvestFileSuppressAllWarnings>
<HarvestFileSuppressSpecificWarnings Condition=" '$(HarvestFileSuppressSpecificWarnings)' == '' ">$(HarvestSuppressSpecificWarnings)</HarvestFileSuppressSpecificWarnings>
<HarvestFileTreatWarningsAsErrors Condition=" '$(HarvestFileTreatWarningsAsErrors)' == '' ">$(HarvestTreatWarningsAsErrors)</HarvestFileTreatWarningsAsErrors>
<HarvestFileTreatSpecificWarningsAsErrors Condition=" '$(HarvestFileTreatSpecificWarningsAsErrors)' == '' ">$(HarvestTreatSpecificWarningsAsErrors)</HarvestFileTreatSpecificWarningsAsErrors>
<HarvestFileVerboseOutput Condition=" '$(HarvestFileVerboseOutput)' == '' ">$(HarvestVerboseOutput)</HarvestFileVerboseOutput>
<HarvestFileAutogenerateGuids Condition=" '$(HarvestFileAutogenerateGuids)' == '' ">$(HarvestAutogenerateGuids)</HarvestFileAutogenerateGuids>
<HarvestFileGenerateGuidsNow Condition=" '$(HarvestFileGenerateGuidsNow)' == '' ">$(HarvestGenerateGuidsNow)</HarvestFileGenerateGuidsNow>
<HarvestFileSuppressFragments Condition=" '$(HarvestFileSuppressFragments)' == '' ">$(HarvestSuppressFragments)</HarvestFileSuppressFragments>
<HarvestFileSuppressUniqueIds Condition=" '$(HarvestFileSuppressUniqueIds)' == '' ">$(HarvestSuppressUniqueIds)</HarvestFileSuppressUniqueIds>
<HarvestFileTransforms Condition=" '$(HarvestFileTransforms)' == '' ">$(HarvestTransforms)</HarvestFileTransforms>
</PropertyGroup>
<!--
==================================================================================================
Harvest
==================================================================================================
-->
<PropertyGroup>
<HarvestDependsOn>
ConvertReferences;
ConvertBundleReferences;
HarvestProjects;
HarvestDirectory;
HarvestFile;
GenerateCode;
</HarvestDependsOn>
</PropertyGroup>
<Target
Name="Harvest"
DependsOnTargets="$(HarvestDependsOn)" />
<!--
==================================================================================================
GenerateCode
==================================================================================================
-->
<PropertyGroup>
<GenerateCodeDependsOn>
RefreshGeneratedFile;
RefreshBundleGeneratedFile
</GenerateCodeDependsOn>
</PropertyGroup>
<Target
Name="GenerateCode"
DependsOnTargets="$(GenerateCodeDependsOn)" />
<!--
================================================================================================
ConvertReferences
Converts project references to HeatProject items to auto generate authoring.
================================================================================================
-->
<Target
Name="ConvertReferences"
Condition=" $(EnableProjectHarvesting) and ('$(OutputType)' == 'Package' or '$(OutputType)' == 'PatchCreation' or '$(OutputType)' == 'Module') ">
<ItemGroup>
<_HeatProjectReference Include="@(_MSBuildProjectReferenceExistent)" Condition=" '%(_MSBuildProjectReferenceExistent.DoNotHarvest)' == '' ">
<DirectoryIds>%(_MSBuildProjectReferenceExistent.RefTargetDir)</DirectoryIds>
<ProjectOutputGroups>Binaries;Symbols;Sources;Content;Satellites;Documents</ProjectOutputGroups>
<ProjectName>%(_MSBuildProjectReferenceExistent.Name)</ProjectName>
<HeatOutput>$(IntermediateOutputPath)_%(_MSBuildProjectReferenceExistent.Filename).wxs</HeatOutput>
</_HeatProjectReference>
<HeatProject Include="@(_HeatProjectReference)" />
</ItemGroup>
<Error
Text="The following files are deprecated and should be removed from your project(s): @(Compile->'%(Identity)', ', ')"
Condition=" '%(Compile.GenerateComponentGroups)' != '' " />
<ItemGroup>
<!-- Unconditionally generate Compile items so they are always linked in. -->
<Compile Include="$(HarvestProjectsGeneratedFile)" />
<_GeneratedFiles Include="$(HarvestProjectsGeneratedFile)" />
</ItemGroup>
</Target>
<!--
================================================================================================
ConvertBundleReferences
Converts project references in Bundle projects to HeatProject items to auto generate authoring.
================================================================================================
-->
<Target
Name="ConvertBundleReferences"
Condition=" $(EnableProjectHarvesting) and ('$(OutputType)' == 'Bundle') ">
<ItemGroup>
<_HeatProjectReference Include="@(_MSBuildProjectReferenceExistent)" Condition=" '%(_MSBuildProjectReferenceExistent.DoNotHarvest)' == '' ">
<ProjectOutputGroups>Binaries;Symbols;Sources;Content;Satellites;Documents</ProjectOutputGroups>
<GenerateType>payloadgroup</GenerateType>
<HeatOutput>$(IntermediateOutputPath)_%(_MSBuildProjectReferenceExistent.Filename).wxs</HeatOutput>
</_HeatProjectReference>
<HeatProject Include="@(_HeatProjectReference)" />
</ItemGroup>
<Error
Text="The following files are deprecated and should be removed from your project(s): @(Compile->'%(Identity)', ', ')"
Condition=" '%(Compile.GenerateComponentGroups)' != '' " />
<ItemGroup>
<!-- Unconditionally generate Compile items so they are always linked in. -->
<Compile Include="$(HarvestProjectsGeneratedFile)" />
<_GeneratedFiles Include="$(HarvestProjectsGeneratedFile)" />
</ItemGroup>
</Target>
<!--
================================================================================================
CombineHarvestProjects
Combines HeatProject and HarvestProject items together and ensures each has HeatOutput metadata.
================================================================================================
-->
<Target
Name="CombineHarvestProjects"
Condition=" '@(HeatProject)' != '' or '@(HarvestProject)' != '' ">
<!-- Add default HeatOutputs for those without one specified -->
<CreateItem Include="@(HeatProject)" Condition= " '%(HeatProject.HeatOutput)' == '' "
AdditionalMetadata="HeatOutput=$(IntermediateOutputPath)_%(HeatProject.Filename).wxs">
<Output TaskParameter="Include" ItemName="_AllHeatProjects" />
</CreateItem>
<CreateItem Include="@(HarvestProject)" Condition= " '%(HarvestProject.HeatOutput)' == '' "
AdditionalMetadata="HeatOutput=$(IntermediateOutputPath)_%(HarvestProject.Filename).wxs">
<Output TaskParameter="Include" ItemName="_AllHeatProjects" />
</CreateItem>
<CreateItem Include="@(HeatProject)" Condition= " '%(HeatProject.HeatOutput)' != '' ">
<Output TaskParameter="Include" ItemName="_AllHeatProjects" />
</CreateItem>
<CreateItem Include="@(HarvestProject)" Condition= " '%(HarvestProject.HeatOutput)' != '' ">
<Output TaskParameter="Include" ItemName="_AllHeatProjects" />
</CreateItem>
</Target>
<!--
================================================================================================
HarvestProjects
Harvests outputs of other MSBuild projects files using the VS project extension to heat.exe.
[IN]
@(HarvestProject)
@(HeatProject)
- The list of projects to harvest. HeatProject is provided for backward compatibility.
You should use HarvestProject instead.
%(HarvestProject.Transforms)
%(HeatProject.Transforms)
- XSL transforms to apply to the harvested WiX.
%(HarvestProject.ProjectOutputGroups)
%(HeatProjects.ProjectOutputGroups)
- The project output groups to harvest
[OUT]
%(HeatOutput)
- The generated .wxs files which are added to the @(Compile) item list.
================================================================================================
-->
<ItemDefinitionGroup>
<HeatProject>
<Transforms>$(HarvestProjectsTransforms)</Transforms>
<ProjectOutputGroups>$(HarvestProjectsProjectOutputGroups)</ProjectOutputGroups>
<DirectoryIds>$(HarvestProjectsDirectoryIds)</DirectoryIds>
</HeatProject>
<HarvestProject>
<Transforms>$(HarvestProjectsTransforms)</Transforms>
<ProjectOutputGroups>$(HarvestProjectsProjectOutputGroups)</ProjectOutputGroups>
<DirectoryIds>$(HarvestProjectsDirectoryIds)</DirectoryIds>
</HarvestProject>
</ItemDefinitionGroup>
<PropertyGroup>
<HarvestProjectsDependsOn>CombineHarvestProjects</HarvestProjectsDependsOn>
</PropertyGroup>
<Target Name="HarvestProjects"
DependsOnTargets="$(HarvestProjectsDependsOn)"
Inputs="@(_AllHeatProjects);%(_AllHeatProjects.Transforms);$(MSBuildAllProjects);$(ProjectPath)"
Outputs="@(_AllHeatProjects -> '%(HeatOutput)')"
Condition=" $(EnableProjectHarvesting) and ('@(HeatProject)' != '' or '@(HarvestProject)' != '') ">
<HeatProject
NoLogo="$(HarvestProjectsNoLogo)"
SuppressAllWarnings="$(HarvestProjectsSuppressAllWarnings)"
SuppressSpecificWarnings="$(HarvestProjectsSuppressSpecificWarnings)"
ToolPath="$(WixToolPath)"
TreatWarningsAsErrors="$(HarvestProjectsTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(HarvestProjectsTreatSpecificWarningsAsErrors)"
VerboseOutput="$(HarvestProjectsVerboseOutput)"
AutogenerateGuids="$(HarvestProjectsAutogenerateGuids)"
GenerateGuidsNow="$(HarvestProjectsGenerateGuidsNow)"
OutputFile="%(_AllHeatProjects.HeatOutput)"
SuppressFragments="$(HarvestProjectsSuppressFragments)"
SuppressUniqueIds="$(HarvestProjectsSuppressUniqueIds)"
Transforms="%(_AllHeatProjects.Transforms)"
Project="%(_AllHeatProjects.FullPath)"
ProjectOutputGroups="%(_AllHeatProjects.ProjectOutputGroups)"
GenerateType="%(_AllHeatProjects.GenerateType)"
DirectoryIds="%(_AllHeatProjects.DirectoryIds)"
ProjectName="%(_AllHeatProjects.ProjectName)"
Configuration="%(_AllHeatProjects.Configuration)"
Platform="%(_AllHeatProjects.Platform)"
RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
GenerateWixVariables="$(HarvestProjectsGenerateWixVariables)"
AdditionalOptions="$(HarvestProjectsAdditionalOptions)">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</HeatProject>
</Target>
<!--
================================================================================================
HarvestDirectory
Harvests directories using heat.exe.
[IN]
@(HarvestDirectory) - The list of directories to harvest.
%(HarvestDirectory.Transforms) - XSL transforms to apply to the harvested WiX.
%(HarvestDirectory.ComponentGroupName) - The name of the ComponentGroup to create.
%(HarvestDirectory.DirectoryRefId) - The ID of the directory to reference instead of TARGETDIR.
%(HarvestDirectory.KeepEmptyDirectories) - Whether to create Directory entries for empty directories.
%(HarvestDirectory.PreprocessorVariable) - Substitute SourceDir for another variable name (ex: var.Dir).
%(HarvestDirectory.SuppressCom) - Suppress COM elements.
%(HarvestDirectory.SuppressRootDirectory) - Suppress a Directory element for the root directory.
$(HarvestDirectory.SuppressRegistry) - Suppress registry harvesting.
[OUT]
$(IntermediateOutputPath)_%(HarvestDirectory.ComponentGroupName)_dir.wxs
- The generated .wxs files which are added to the @(Compile) item list.
================================================================================================
-->
<ItemDefinitionGroup>
<HarvestDirectory>
<Transforms>$(HarvestDirectoryTransforms)</Transforms>
<ComponentGroupName>$(HarvestDirectoryComponentGroupName)</ComponentGroupName>
<DirectoryRefId>$(HarvestDirectoryDirectoryRefId)</DirectoryRefId>
<KeepEmptyDirectories>$(HarvestDirectoryKeepEmptyDirectories)</KeepEmptyDirectories>
<PreprocessorVariable>$(HarvestDirectoryPreprocessorVariable)</PreprocessorVariable>
<SuppressCom>$(HarvestDirectorySuppressCom)</SuppressCom>
<SuppressRootDirectory>$(HarvestDirectorySuppressRootDirectory)</SuppressRootDirectory>
<SuppressRegistry>$(HarvestDirectorySuppressRegistry)</SuppressRegistry>
</HarvestDirectory>
</ItemDefinitionGroup>
<PropertyGroup>
<HarvestDirectoryDependsOn>
GetHarvestDirectoryContent
</HarvestDirectoryDependsOn>
</PropertyGroup>
<!-- Creates items to include content since wildcards will not work in Target/@Inputs. -->
<Target Name="GetHarvestDirectoryContent">
<CreateItem Include="@(HarvestDirectory->'%(FullPath)\**\*')">
<Output TaskParameter="Include" ItemName="_HarvestDirectoryContent" />
</CreateItem>
</Target>
<Target Name="HarvestDirectory"
DependsOnTargets="$(HarvestDirectoryDependsOn)"
Inputs="@(_HarvestDirectoryContent);%(HarvestDirectory.Transforms)"
Outputs="$(IntermediateOutputPath)_%(HarvestDirectory.ComponentGroupName)_dir.wxs"
Condition=" '@(HarvestDirectory)' != '' ">
<HeatDirectory
NoLogo="$(HarvestDirectoryNoLogo)"
SuppressAllWarnings="$(HarvestDirectorySuppressAllWarnings)"
SuppressSpecificWarnings="$(HarvestDirectorySuppressSpecificWarnings)"
ToolPath="$(WixToolPath)"
TreatWarningsAsErrors="$(HarvestDirectoryTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(HarvestDirectoryTreatSpecificWarningsAsErrors)"
VerboseOutput="$(HarvestDirectoryVerboseOutput)"
AutogenerateGuids="$(HarvestDirectoryAutogenerateGuids)"
GenerateGuidsNow="$(HarvestDirectoryGenerateGuidsNow)"
OutputFile="$(IntermediateOutputPath)_%(HarvestDirectory.ComponentGroupName)_dir.wxs"
SuppressFragments="$(HarvestDirectorySuppressFragments)"
SuppressUniqueIds="$(HarvestDirectorySuppressUniqueIds)"
Transforms="%(HarvestDirectory.Transforms)"
Directory="@(HarvestDirectory)"
ComponentGroupName="%(HarvestDirectory.ComponentGroupName)"
DirectoryRefId="%(HarvestDirectory.DirectoryRefId)"
KeepEmptyDirectories="%(HarvestDirectory.KeepEmptyDirectories)"
PreprocessorVariable="%(HarvestDirectory.PreprocessorVariable)"
RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
SuppressCom="%(HarvestDirectory.SuppressCom)"
SuppressRootDirectory="%(HarvestDirectory.SuppressRootDirectory)"
SuppressRegistry="%(HarvestDirectory.SuppressRegistry)"
AdditionalOptions="$(HarvestDirectoryAdditionalOptions)">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</HeatDirectory>
</Target>
<!--
================================================================================================
HarvestFile
Harvests files of different types using heat.exe. This can harvest registry from
self-registering files, files with typelibs, and more.
[IN]
@(HarvestFile) - The list of files to harvest.
%(HarvestFile.Transforms) - XSL transforms to apply to the harvested WiX.
%(HarvestFile.ComponentGroupName) - The name of the ComponentGroup to create.
%(HarvestFile.DirectoryRefId) - The ID of the directory to reference instead of TARGETDIR.
%(HarvestFile.PreprocessorVariable) - Substitute SourceDir for another variable name (ex: var.Dir).
%(HarvestFile.SuppressCom) - Suppress COM elements.
%(HarvestFile.SuppressRootDirectory) - Suppress a Directory element for the root directory.
$(HarvestFile.SuppressRegistry) - Suppress registry harvesting.
[OUT]
$(IntermediateOutputPath)_%(HarvestFile.Filename)_file.wxs
- The generated .wxs files which are added to the @(Compile) item list.
================================================================================================
-->
<ItemDefinitionGroup>
<HarvestFile>
<Transforms>$(HarvestFileTransforms)</Transforms>
<ComponentGroupName>$(HarvestFileComponentGroupName)</ComponentGroupName>
<DirectoryRefId>$(HarvestFileDirectoryRefId)</DirectoryRefId>
<PreprocessorVariable>$(HarvestFilePreprocessorVariable)</PreprocessorVariable>
<SuppressCom>$(HarvestFileSuppressCom)</SuppressCom>
<SuppressRegistry>$(HarvestFileSuppressRegistry)</SuppressRegistry>
<SuppressRootDirectory>$(HarvestFileSuppressRootDirectory)</SuppressRootDirectory>
</HarvestFile>
</ItemDefinitionGroup>
<PropertyGroup>
<HarvestFileDependsOn></HarvestFileDependsOn>
</PropertyGroup>
<Target Name="HarvestFile"
DependsOnTargets="$(HarvestFileDependsOn)"
Inputs="@(HarvestFile);%(HarvestFile.Transforms)"
Outputs="$(IntermediateOutputPath)_%(HarvestFile.Filename)_file.wxs"
Condition=" '@(HarvestFile)' != '' ">
<HeatFile
NoLogo="$(HarvestFileNoLogo)"
SuppressAllWarnings="$(HarvestFileSuppressAllWarnings)"
SuppressSpecificWarnings="$(HarvestFileSuppressSpecificWarnings)"
ToolPath="$(WixToolPath)"
TreatWarningsAsErrors="$(HarvestFileTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(HarvestFileTreatSpecificWarningsAsErrors)"
VerboseOutput="$(HarvestFileVerboseOutput)"
AutogenerateGuids="$(HarvestFileAutogenerateGuids)"
GenerateGuidsNow="$(HarvestFileGenerateGuidsNow)"
OutputFile="$(IntermediateOutputPath)_%(HarvestFile.Filename)_file.wxs"
SuppressFragments="$(HarvestFileSuppressFragments)"
SuppressUniqueIds="$(HarvestFileSuppressUniqueIds)"
Transforms="%(HarvestFile.Transforms)"
File="@(HarvestFile)"
ComponentGroupName="%(HarvestFile.ComponentGroupName)"
DirectoryRefId="%(HarvestFile.DirectoryRefId)"
PreprocessorVariable="%(HarvestFile.PreprocessorVariable)"
RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
SuppressCom="%(HarvestFile.SuppressCom)"
SuppressRegistry="%(HarvestFile.SuppressRegistry)"
SuppressRootDirectory="%(HarvestFile.SuppressRootDirectory)"
AdditionalOptions="$(HarvestFileAdditionalOptions)">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</HeatFile>
</Target>
<!--
================================================================================================
RefreshGeneratedFile
Generates code based on metadata defined in project references.
[IN]
@(_MSBuildResolvedProjectReferencePaths) - The list of MSBuildable project references.
[OUT]
@(_GeneratedFiles) - The generated source file.
================================================================================================
-->
<PropertyGroup>
<RefreshGeneratedFileDependsOn></RefreshGeneratedFileDependsOn>
</PropertyGroup>
<Target Name="RefreshGeneratedFile"
DependsOnTargets="$(RefreshGeneratedFileDependsOn)"
Inputs="@(_MSBuildResolvedProjectReferencePaths);@(Compile);$(ProjectPath)"
Outputs="@(_GeneratedFiles)"
Condition=" $(EnableProjectHarvesting) and ('$(OutputType)' == 'Package' or '$(OutputType)' == 'PatchCreation' or '$(OutputType)' == 'Module') and '@(_GeneratedFiles)' != '' ">
<RefreshGeneratedFile
GeneratedFiles="@(_GeneratedFiles)"
ProjectReferencePaths="@(_MSBuildResolvedProjectReferencePaths)" />
</Target>
<!--
================================================================================================
RefreshBundleGeneratedFile
Generates code for bundle projects based on metadata defined in project references.
[IN]
@(_MSBuildResolvedProjectReferencePaths) - The list of MSBuildable project references.
[OUT]
@(_GeneratedFiles) - The generated source file.
================================================================================================
-->
<PropertyGroup>
<RefreshBundleGeneratedFileDependsOn></RefreshBundleGeneratedFileDependsOn>
</PropertyGroup>
<Target Name="RefreshBundleGeneratedFile"
DependsOnTargets="$(RefreshBundleGeneratedFileDependsOn)"
Inputs="@(_MSBuildResolvedProjectReferencePaths);@(Compile);$(ProjectPath)"
Outputs="@(_GeneratedFiles)"
Condition=" $(EnableProjectHarvesting) and ('$(OutputType)' == 'Bundle' and '@(_GeneratedFiles)' != '') ">
<RefreshBundleGeneratedFile
GeneratedFiles="@(_GeneratedFiles)"
ProjectReferencePaths="@(_MSBuildResolvedProjectReferencePaths)" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,378 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- These properties can be overridden to support non-default installations. -->
<PropertyGroup>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildThisFileFullPath)</WixTargetsPath>
<WixTasksPath Condition=" '$(WixTasksPath)' == '' ">$(WixTargetsPath)WixTasks.dll</WixTasksPath>
<SignedFile Condition=" '$(SignedFile)' == '' ">$(MSBuildProjectFile).Signed.txt</SignedFile>
</PropertyGroup>
<UsingTask TaskName="Insignia" AssemblyFile="$(WixTasksPath)" />
<!-- Default Inscribe properties. -->
<PropertyGroup>
<InscribeNoLogo Condition=" '$(InscribeNoLogo)' == '' ">$(NoLogo)</InscribeNoLogo>
<InscribeSuppressAllWarnings Condition=" '$(InscribeSuppressAllWarnings)' == '' ">$(SuppressAllWarnings)</InscribeSuppressAllWarnings>
<InscribeSuppressSpecificWarnings Condition=" '$(InscribeSuppressSpecificWarnings)' == '' ">$(SuppressSpecificWarnings)</InscribeSuppressSpecificWarnings>
<InscribeTreatWarningsAsErrors Condition=" '$(InscribeTreatWarningsAsErrors)' == '' ">$(TreatWarningsAsErrors)</InscribeTreatWarningsAsErrors>
<InscribeTreatSpecificWarningsAsErrors Condition=" '$(InscribeTreatSpecificWarningsAsErrors)' == '' ">$(TreatSpecificWarningsAsErrors)</InscribeTreatSpecificWarningsAsErrors>
<InscribeVerboseOutput Condition=" '$(InscribeVerboseOutput)' == '' ">$(VerboseOutput)</InscribeVerboseOutput>
</PropertyGroup>
<!--
==================================================================================================
Signing
==================================================================================================
-->
<PropertyGroup>
<InternalSignDependsOn Condition=" '$(OutputType)' == 'Module' ">
GetMsmsToSign;
InternalSignMsm;
</InternalSignDependsOn>
<InternalSignDependsOn Condition=" '$(OutputType)' == 'Package' ">
GetCabsToSign;
GetMsiToSign;
InternalSignCabs;
InscribeMsi;
InternalSignMsi;
</InternalSignDependsOn>
<InternalSignDependsOn Condition=" '$(OutputType)' == 'Bundle' ">
GetContainersToSign;
InternalSignContainers;
InscribeBundleEngine;
InternalSignBundleEngine;
InscribeBundle;
InternalSignBundle;
</InternalSignDependsOn>
<SigningDependsOn>
CompileAndLink;
BeforeSigning;
$(InternalSignDependsOn);
AfterSigning
</SigningDependsOn>
</PropertyGroup>
<Target
Name="Signing"
DependsOnTargets="$(SigningDependsOn)"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)"
Condition=" '@(SignTargetPath)' != '' ">
<CreateItem Include="$(IntermediateOutputPath)$(SignedFile)">
<Output TaskParameter="Include" ItemName="FileWrites" />
</CreateItem>
<WriteLinesToFile
File="$(IntermediateOutputPath)$(SignedFile)"
Lines="^$(MSBuildProjectFullPath);@(SignMsm);@(SignCabs);@(SignMsi);@(SignContainers);@(SignBundleEngine);@(SignBundle)"
Overwrite="true" />
</Target>
<!-- Internal targets so correct signing targets are called. -->
<Target
Name="GetMsmsToSign"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)">
<CreateItem Include="@(SignTargetPath)">
<Output TaskParameter="Include" ItemName="SignMsm" />
<Output TaskParameter="Include" ItemName="FileWrites" />
</CreateItem>
</Target>
<Target
Name="InternalSignMsm"
DependsOnTargets="SignMsm"
Condition=" '@(SignMsm)' != '' " />
<Target
Name="GetCabsToSign"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)">
<GetCabList Database="%(SignTargetPath.FullPath)">
<Output TaskParameter="CabList" ItemName="SignCabs" />
<Output TaskParameter="CabList" ItemName="FileWrites" />
</GetCabList>
</Target>
<Target
Name="InternalSignCabs"
DependsOnTargets="SignCabs"
Condition=" '@(SignCabs)' != '' " />
<Target
Name="GetMsiToSign"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)">
<CreateItemAvoidingInference InputProperties="@(SignTargetPath)">
<Output TaskParameter="OuputItems" ItemName="SignMsi" />
<Output TaskParameter="OuputItems" ItemName="FileWrites" />
</CreateItemAvoidingInference>
</Target>
<Target
Name="InternalSignMsi"
DependsOnTargets="SignMsi"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)"
Condition=" '@(SignMsi)' != '' " />
<Target
Name="GetContainersToSign"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)">
<!-- TODO: implement signing detached containers -->
</Target>
<Target
Name="InternalSignContainers"
DependsOnTargets="SignContainers"
Condition=" '@(SignContainers)' != '' " />
<Target
Name="InternalSignBundleEngine"
DependsOnTargets="SignBundleEngine"
Condition=" '@(SignBundleEngine)' != '' " />
<Target
Name="InternalSignBundle"
DependsOnTargets="SignBundle"
Condition=" '@(SignBundle)' != '' " />
<!--
================================================================================================
InscribeMsi
To be called after signing an MSI's cabs - inscribes an MSI with the digital signature of its
external cabs.
[IN/OUT]
@(SignTargetPath) - The database file to inscribe - database file will be modified in-place.
[OUT]
@(SignMsi) - The database file to sign.
================================================================================================
-->
<PropertyGroup>
<InscribeMsiDependsOn>
PrepareForBuild;
ResolveWixExtensionReferences;
CompileAndLink;
InternalSignCabs
</InscribeMsiDependsOn>
</PropertyGroup>
<Target
Name="InscribeMsi"
DependsOnTargets="$(InscribeMsiDependsOn)"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)"
Condition=" '@(SignCabs)' != '' ">
<Insignia
DatabaseFile="%(SignTargetPath.FullPath)"
OutputFile="%(SignTargetPath.FullPath)"
ToolPath="$(WixToolPath)"
NoLogo="$(InscribeNoLogo)"
RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
SuppressAllWarnings="$(InscribeSuppressAllWarnings)"
SuppressSpecificWarnings="$(InscribeSuppressSpecificWarnings)"
TreatWarningsAsErrors="$(InscribeTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(InscribeTreatSpecificWarningsAsErrors)"
VerboseOutput="$(InscribeVerboseOutput)"
AdditionalOptions="$(InscribeAdditionalOptions)" />
</Target>
<!--
================================================================================================
InscribeBundleEngine
To be called after signing a bundle's detached containers. Also removes attached container
so engine can be signed without attached container.
[IN]
@(SignTargetPath) - The bundle to inscribe.
[OUT]
@(SignBundleEngine) - The bundle engine file to be signed.
================================================================================================
-->
<PropertyGroup>
<InscribeBundleEngineDependsOn>
PrepareForBuild;
ResolveWixExtensionReferences;
CompileAndLink;
InternalSignContainers
</InscribeBundleEngineDependsOn>
</PropertyGroup>
<Target
Name="InscribeBundleEngine"
DependsOnTargets="$(InscribeBundleEngineDependsOn)"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)">
<Insignia
BundleFile="@(SignTargetPath)"
OutputFile="$(IntermediateOutputPath)%(SignTargetPath.Filename)%(SignTargetPath.Extension)"
ToolPath="$(WixToolPath)"
NoLogo="$(InscribeNoLogo)"
RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
SuppressAllWarnings="$(InscribeSuppressAllWarnings)"
SuppressSpecificWarnings="$(InscribeSuppressSpecificWarnings)"
TreatWarningsAsErrors="$(InscribeTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(InscribeTreatSpecificWarningsAsErrors)"
VerboseOutput="$(InscribeVerboseOutput)"
AdditionalOptions="$(InscribeAdditionalOptions)">
<Output TaskParameter="Output" ItemName="SignBundleEngine" />
</Insignia>
<!-- Explicitly add output to FileWrites to ensure even when the target is up to date. -->
<CreateItem Include="$(IntermediateOutputPath)%(SignTargetPath.Filename)%(SignTargetPath.Extension)">
<Output TaskParameter="Include" ItemName="FileWrites" />
</CreateItem>
</Target>
<!--
================================================================================================
InscribeBundle
To be called after signing the bundle engine to reattach the attached container.
[IN]
@(Inscribe) - The bundle to inscribe.
[OUT]
@(SignBundle) - The bundle engine file to be signed.
================================================================================================
-->
<PropertyGroup>
<InscribeBundleDependsOn>
PrepareForBuild;
ResolveWixExtensionReferences;
CompileAndLink;
InternalSignBundleEngine
</InscribeBundleDependsOn>
</PropertyGroup>
<Target
Name="InscribeBundle"
DependsOnTargets="$(InscribeBundleDependsOn)"
Inputs="@(SignTargetPath)"
Outputs="$(IntermediateOutputPath)$(SignedFile)">
<Insignia
BundleFile="@(SignBundleEngine)"
OriginalBundleFile="@(SignTargetPath)"
OutputFile="@(SignTargetPath)"
ToolPath="$(WixToolPath)"
NoLogo="$(InscribeNoLogo)"
RunAsSeparateProcess="$(RunWixToolsOutOfProc)"
SuppressAllWarnings="$(InscribeSuppressAllWarnings)"
SuppressSpecificWarnings="$(InscribeSuppressSpecificWarnings)"
TreatWarningsAsErrors="$(InscribeTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(InscribeTreatSpecificWarningsAsErrors)"
VerboseOutput="$(InscribeVerboseOutput)"
AdditionalOptions="$(InscribeAdditionalOptions)">
<Output TaskParameter="Output" ItemName="SignBundle" />
<Output TaskParameter="Output" ItemName="FileWrites" />
</Insignia>
</Target>
<!--
==================================================================================================
BeforeSigning
Redefine this target in your project in order to run tasks just before all signing tasks.
==================================================================================================
-->
<Target Name="BeforeSigning" />
<!--
==================================================================================================
SignMsm
Redefine this target in your project in order to sign merge modules.
[IN]
@(SignMsm) - merge module files to sign.
==================================================================================================
-->
<Target Name="SignMsm" />
<!--
==================================================================================================
SignCabs
Redefine this target in your project in order to sign the cabs of your database.
[IN]
@(SignCabs) - cabinet files to sign.
==================================================================================================
-->
<Target Name="SignCabs" />
<!--
==================================================================================================
SignMsi
Redefine this target in your project in order to sign your database, after it has been inscribed
with the signatures of your signed cabs.
[IN]
@(SignMsi) - database files to sign.
==================================================================================================
-->
<Target Name="SignMsi" />
<!--
==================================================================================================
SignContainers
Redefine this target in your project in order to sign your bundle's detached containers.
[IN]
@(SignContainers) - detached container files to sign.
==================================================================================================
-->
<Target Name="SignContainers" />
<!--
==================================================================================================
SignBundleEngine
Redefine this target in your project in order to sign your bundle, after it has been inscribed
with the signatures of your signed containers.
[IN]
@(SignBundleEngine) - bundle engine file to sign.
==================================================================================================
-->
<Target Name="SignBundleEngine" />
<!--
==================================================================================================
SignBundle
Redefine this target in your project in order to sign your bundle, after the attached container
is reattached.
[IN]
@(SignBundle) - bundle file to sign.
==================================================================================================
-->
<Target Name="SignBundle" />
<!--
==================================================================================================
AfterSigning
Redefine this target in your project in order to run tasks just after all signing tasks.
==================================================================================================
-->
<Target Name="AfterSigning" />
</Project>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IncludeBuildOutput>false</IncludeBuildOutput>
<Description>Internal WiX Toolset Tools</Description>
<NuspecFile>$(MSBuildThisFileName).nuspec</NuspecFile>
<NuspecBasePath>$(OutputPath)publish</NuspecBasePath>
<NuspecProperties>Id=$(MSBuildThisFileName);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description)</NuspecProperties>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetNuspecVersion</GenerateNuspecDependsOn>
</PropertyGroup>
<Target Name="SetNuspecVersion">
<Error Text="Cannot pack $(MSBuildThisFileName) until all projects are published to: '$(NuspecBasePath)'. Run appveyor.cmd to publish projects properly." Condition=" !Exists('$(NuspecBasePath)') " />
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);Version=$(Version);ProjectFolder=$(MSBuildThisFileDirectory)</NuspecProperties>
</PropertyGroup>
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
<owners>$authors$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>$copyright$</copyright>
</metadata>
<files>
<file src="$projectFolder$$id$.props" target="build" />
<file src="netcoreapp2.1\*" target="tools\netcoreapp2.1" />
<file src="net461\*" target="tools\net461" />
<file src="net461\redirects\*" target="msbuild" />
</files>
</package>

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\net461\wix.targets</WixTargetsPath>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IncludeBuildOutput>false</IncludeBuildOutput>
<Description>WiX Toolset MSBuild integration</Description>
<NuspecFile>$(MSBuildThisFileName).nuspec</NuspecFile>
<NuspecBasePath>$(OutputPath)publish\WixToolset.MSBuild\</NuspecBasePath>
<NuspecProperties>Id=$(MSBuildThisFileName);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description)</NuspecProperties>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetNuspecVersion</GenerateNuspecDependsOn>
</PropertyGroup>
<Target Name="SetNuspecVersion">
<Error Text="Cannot pack $(MSBuildThisFileName) until all projects are published to: '$(NuspecBasePath)'. Run appveyor.cmd to publish projects properly." Condition=" !Exists('$(NuspecBasePath)') " />
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);Version=$(Version);ProjectFolder=$(MSBuildThisFileDirectory)</NuspecProperties>
</PropertyGroup>
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
<owners>$authors$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>$copyright$</copyright>
</metadata>
<files>
<file src="$projectFolder$$id$.props" target="build" />
<file src="net461\*" target="tools\net461" />
<file src="net461\runtimes\win-x86\native\*.exe" target="tools\net461" />
<file src="netcoreapp2.1\*" target="tools\netcoreapp2.1" />
<file src="netcoreapp2.1\runtimes\**" target="tools\netcoreapp2.1\runtimes" />
<file src="netcoreapp2.1\runtimes\win-x86\native\*.exe" target="tools\netcoreapp2.1" />
</files>
</package>

Просмотреть файл

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' and '$(MSBuildRuntimeType)' == 'Core' ">$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\tools\netcoreapp2.1\wix.targets'))</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\tools\net461\wix.targets'))</WixTargetsPath>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<DotNetCliTool Version="1">
<Commands>
<Command Name="wix" EntryPoint="wix.dll" Runner="dotnet" />
</Commands>
</DotNetCliTool>

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IncludeBuildOutput>false</IncludeBuildOutput>
<Description>WiX Toolset Command-line interface</Description>
<NuspecFile>$(MSBuildThisFileName).nuspec</NuspecFile>
<NuspecBasePath>$(OutputPath)publish\dotnet-wix\</NuspecBasePath>
<NuspecProperties>Id=$(MSBuildThisFileName);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description)</NuspecProperties>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetNuspecVersion</GenerateNuspecDependsOn>
</PropertyGroup>
<Target Name="SetNuspecVersion">
<Error Text="Cannot pack $(MSBuildThisFileName) until all projects are published to: '$(NuspecBasePath)'. Run appveyor.cmd to publish projects properly." Condition=" !Exists('$(NuspecBasePath)') " />
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);Version=$(Version);ProjectFolder=$(MSBuildThisFileDirectory)</NuspecProperties>
</PropertyGroup>
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
<owners>$authors$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>$copyright$</copyright>
<packageTypes>
<packageType name="DotnetTool" />
</packageTypes>
<dependencies>
<group targetFramework=".NETCoreApp2.1" />
</dependencies>
</metadata>
<files>
<file src="$projectFolder$DotnetToolSettings.xml" target="tools\netcoreapp2.1\any" />
<file src="**" target="tools\netcoreapp2.1\any" />
<file src="runtimes\win-x86\native\*.exe" target="tools\netcoreapp2.1\any" />
</files>
</package>

Просмотреть файл

@ -0,0 +1,33 @@
// 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.
namespace WixToolsetTest.BuildTasks
{
using System.Collections;
using System.Text;
using Microsoft.Build.Framework;
internal class FakeBuildEngine : IBuildEngine
{
private StringBuilder output = new StringBuilder();
public int ColumnNumberOfTaskNode => 0;
public bool ContinueOnError => false;
public int LineNumberOfTaskNode => 0;
public string ProjectFileOfTaskNode => "fake_wix.targets";
public string Output => this.output.ToString();
public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) => throw new System.NotImplementedException();
public void LogCustomEvent(CustomBuildEventArgs e) => this.output.AppendLine(e.Message);
public void LogErrorEvent(BuildErrorEventArgs e) => this.output.AppendLine(e.Message);
public void LogMessageEvent(BuildMessageEventArgs e) => this.output.AppendLine(e.Message);
public void LogWarningEvent(BuildWarningEventArgs e) => this.output.AppendLine(e.Message);
}
}

Просмотреть файл

@ -0,0 +1,64 @@
// 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.
namespace WixToolsetTest.BuildTasks
{
using System.IO;
using System.Linq;
using Microsoft.Build.Utilities;
using WixBuildTools.TestSupport;
using WixToolset.BuildTasks;
using WixToolset.Data;
using WixToolset.Data.Tuples;
using Xunit;
public partial class MsbuildFixture
{
[Fact]
public void CanBuildSimpleMsiPackage()
{
var folder = TestData.Get(@"TestData\SimpleMsiPackage\MsiPackage");
using (var fs = new DisposableFileSystem())
{
var baseFolder = fs.GetFolder();
var intermediateFolder = Path.Combine(baseFolder, "obj");
var engine = new FakeBuildEngine();
var task = new DoIt
{
BuildEngine = engine,
SourceFiles = new[]
{
new TaskItem(Path.Combine(folder, "Package.wxs")),
new TaskItem(Path.Combine(folder, "PackageComponents.wxs")),
},
LocalizationFiles = new[]
{
new TaskItem(Path.Combine(folder, "Package.en-us.wxl")),
},
BindInputPaths = new[]
{
new TaskItem(Path.Combine(folder, "data")),
},
IntermediateDirectory = new TaskItem(intermediateFolder),
OutputFile = new TaskItem(Path.Combine(baseFolder, @"bin\test.msi")),
};
var result = task.Execute();
Assert.True(result, $"MSBuild task failed unexpectedly. Output:\r\n{engine.Output}");
Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.msi")));
Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\cab1.cab")));
var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir"));
var section = intermediate.Sections.Single();
var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
Assert.Equal(Path.Combine(folder, @"data\test.txt"), wixFile[WixFileTupleFields.Source].AsPath().Path);
Assert.Equal(@"test.txt", wixFile[WixFileTupleFields.Source].PreviousValue.AsPath().Path);
}
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>0.9</ProductVersion>
<ProjectGuid>7fb77005-c6e0-454f-8c2d-0a4a79c918ba</ProjectGuid>
<OutputName>MsiPackage</OutputName>
<OutputType>Package</OutputType>
<Name>MsiPackage</Name>
<RootNamespace>MsiPackage</RootNamespace>
<Cultures>en-US,en;de-DE</Cultures>
</PropertyGroup>
<PropertyGroup>
<WixTargetsPath>..\..\..\..\..\..\build\Release\publish\net461\wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Package.wxs" />
<Compile Include="PackageComponents.wxs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Package.en-us.wxl" />
<EmbeddedResource Include="Package.de-de.wxl" />
</ItemGroup>
<ItemGroup>
<BindInputPaths Include="data" />
</ItemGroup>
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="WiX Toolset build tools (v3.11 or later) must be installed to build this project. To download the WiX Toolset, go to http://wixtoolset.org/releases/." />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="de-DE">
<String Id="DowngradeError">German DowngradeError</String>
<String Id="FeatureTitle">German FeatureTitle</String>
</WixLocalization>

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
<String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
<String Id="FeatureTitle">MsiPackage</String>
</WixLocalization>

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Product Id="*" Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
<MediaTemplate />
<Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MsiPackage" />
</Directory>
</Directory>
</Fragment>
</Wix>

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component>
<File Source="test.txt" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>

Просмотреть файл

@ -0,0 +1 @@
This is test.txt.

Просмотреть файл

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.8
MinimumVisualStudioVersion = 10.0.40219.1
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MsiPackage", "MsiPackage\MsiPackage.wixproj", "{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x64.ActiveCfg = Debug|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x64.Build.0 = Debug|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x86.ActiveCfg = Debug|x86
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x86.Build.0 = Debug|x86
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x64.ActiveCfg = Release|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x64.Build.0 = Release|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x86.ActiveCfg = Release|x86
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {585B0599-4EB5-4AB6-BC66-819CC78B63D5}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>0.9</ProductVersion>
<ProjectGuid>7fb77005-c6e0-454f-8c2d-0a4a79c918ba</ProjectGuid>
<OutputName>MsiPackage</OutputName>
<OutputType>Package</OutputType>
<Name>MsiPackage</Name>
<RootNamespace>MsiPackage</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<WixTargetsPath>..\..\..\..\..\..\build\Release\publish\wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<PlatformName>$(Platform)</PlatformName>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Package.wxs" />
<Compile Include="PackageComponents.wxs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Package.en-us.wxl" />
</ItemGroup>
<ItemGroup>
<BindInputPaths Include="data" />
</ItemGroup>
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="WiX Toolset build tools (v3.11 or later) must be installed to build this project. To download the WiX Toolset, go to http://wixtoolset.org/releases/." />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
<String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
<String Id="FeatureTitle">MsiPackage</String>
</WixLocalization>

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Product Id="*" Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
<MediaTemplate />
<Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MsiPackage" />
</Directory>
</Directory>
</Fragment>
</Wix>

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component>
<File Source="test.txt" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>

Просмотреть файл

@ -0,0 +1 @@
This is test.txt.

Просмотреть файл

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.8
MinimumVisualStudioVersion = 10.0.40219.1
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MsiPackage", "MsiPackage\MsiPackage.wixproj", "{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x64.ActiveCfg = Debug|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x64.Build.0 = Debug|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x86.ActiveCfg = Debug|x86
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Debug|x86.Build.0 = Debug|x86
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x64.ActiveCfg = Release|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x64.Build.0 = Release|x64
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x86.ActiveCfg = Release|x86
{7FB77005-C6E0-454F-8C2D-0A4A79C918BA}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {585B0599-4EB5-4AB6-BC66-819CC78B63D5}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<IsPackable>false</IsPackable>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
<Content Include="TestData\SimpleMsiPackage\MsiPackage\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
<Content Include="TestData\SimpleMsiPackage\MsiPackage\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
<Content Include="TestData\SimpleMsiPackage\MsiPackage\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
<Content Include="TestData\SimpleMsiPackage\MsiPackage\data\test.txt" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\WixToolset.BuildTasks\WixToolset.BuildTasks.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="14.3" PrivateAssets="All" />
<PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>
</Project>

123
src/wix/Program.cs Normal file
Просмотреть файл

@ -0,0 +1,123 @@
// 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.
namespace WixToolset.Tools
{
using System;
using System.Globalization;
using System.Text;
using System.Threading;
using WixToolset.Core;
using WixToolset.Data;
using WixToolset.Extensibility;
using WixToolset.Extensibility.Services;
/// <summary>
/// Wix Toolset Command-Line Interface.
/// </summary>
public sealed class Program
{
/// <summary>
/// The main entry point for wix command-line interface.
/// </summary>
/// <param name="args">Commandline arguments for the application.</param>
/// <returns>Returns the application error code.</returns>
[MTAThread]
public static int Main(string[] args)
{
var serviceProvider = new WixToolsetServiceProvider();
var listener = new ConsoleMessageListener("WIX", "wix.exe");
var program = new Program();
return program.Run(serviceProvider, listener, args);
}
/// <summary>
/// Executes the wix command-line interface.
/// </summary>
/// <param name="serviceProvider">Service provider to use throughout this execution.</param>
/// <param name="args">Command-line arguments to execute.</param>
/// <returns>Returns the application error code.</returns>
public int Run(IServiceProvider serviceProvider, IMessageListener listener, string[] args)
{
var messaging = serviceProvider.GetService<IMessaging>();
messaging.SetListener(listener);
var arguments = serviceProvider.GetService<ICommandLineArguments>();
arguments.Populate(args);
var context = serviceProvider.GetService<ICommandLineContext>();
context.Messaging = messaging;
context.ExtensionManager = CreateExtensionManagerWithStandardBackends(serviceProvider, arguments.Extensions);
context.Arguments = arguments;
var commandLine = serviceProvider.GetService<ICommandLine>();
var command = commandLine.ParseStandardCommandLine(context);
return command?.Execute() ?? 1;
}
private static IExtensionManager CreateExtensionManagerWithStandardBackends(IServiceProvider serviceProvider, string[] extensions)
{
var extensionManager = serviceProvider.GetService<IExtensionManager>();
foreach (var type in new[] { typeof(WixToolset.Core.Burn.WixToolsetStandardBackend), typeof(WixToolset.Core.WindowsInstaller.WixToolsetStandardBackend) })
{
extensionManager.Add(type.Assembly);
}
foreach (var extension in extensions)
{
extensionManager.Load(extension);
}
return extensionManager;
}
private class ConsoleMessageListener : IMessageListener
{
public ConsoleMessageListener(string shortName, string longName)
{
this.ShortAppName = shortName;
this.LongAppName = longName;
PrepareConsoleForLocalization();
}
public string LongAppName { get; }
public string ShortAppName { get; }
public void Write(Message message)
{
var filename = message.SourceLineNumbers?.FileName ?? this.LongAppName;
var line = message.SourceLineNumbers?.LineNumber ?? -1;
var type = message.Level.ToString().ToLowerInvariant();
var output = message.Level >= MessageLevel.Warning ? Console.Out : Console.Error;
if (line > 0)
{
filename = String.Concat(filename, "(", line, ")");
}
output.WriteLine("{0} : {1} {2}{3:0000}: {4}", filename, type, this.ShortAppName, message.Id, message.ToString());
}
public void Write(string message)
{
Console.Out.WriteLine(message);
}
private static void PrepareConsoleForLocalization()
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
if (Console.OutputEncoding.CodePage != Encoding.UTF8.CodePage &&
Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage &&
Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
}
}
}
}

34
src/wix/wix.csproj Normal file
Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<OutputType>Exe</OutputType>
<Description>Compiler</Description>
<Title>WiX Toolset Compiler</Title>
<DebugType>embedded</DebugType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<!-- <PackAsTool>true</PackAsTool> -->
</PropertyGroup>
<PropertyGroup>
<NoWarn>NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(WixToolsetRootFolder)\Core\src\WixToolset.Core\WixToolset.Core.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<PackageReference Include="WixToolset.Core" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<ProjectReference Include="$(WixToolsetRootFolder)\Core\src\WixToolset.Core.Burn\WixToolset.Core.Burn.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<ProjectReference Include="$(WixToolsetRootFolder)\Core\src\WixToolset.Core.WindowsInstaller\WixToolset.Core.WindowsInstaller.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Core\README.md') " />
<PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Core\README.md') " />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63102-01" PrivateAssets="All"/>
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" />
</ItemGroup>
</Project>

11
version.json Normal file
Просмотреть файл

@ -0,0 +1,11 @@
{
"version": "4.0.0-build.{height}",
"publicReleaseRefSpec": [
"^refs/heads/master$"
],
"cloudBuild": {
"buildNumber": {
"enabled": true
}
}
}