From 59765d27eb205b7b62a5057cfb631caee97f0af6 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 4 May 2021 22:49:35 -0700 Subject: Move PowerShell.wixext into ext --- src/ext/PowerShell/CSharp.Build.props | 11 + src/ext/PowerShell/Directory.Build.props | 29 +++ src/ext/PowerShell/Directory.Build.targets | 48 ++++ src/ext/PowerShell/FindLocalWix.props | 8 + src/ext/PowerShell/PowerShell.wixext.sln | 63 +++++ src/ext/PowerShell/README.md | 2 + src/ext/PowerShell/appveyor.cmd | 13 + src/ext/PowerShell/appveyor.yml | 40 +++ src/ext/PowerShell/nuget.config | 14 + .../PowerShellExtensionFixture.cs | 26 ++ .../TestData/TypesFile/Package.en-us.wxl | 11 + .../TestData/TypesFile/Package.wxs | 15 ++ .../TestData/TypesFile/PackageComponents.wxs | 13 + .../TestData/TypesFile/example.txt | 1 + .../WixToolsetTest.Powershell.csproj | 41 +++ src/ext/PowerShell/wix.snk | Bin 0 -> 596 bytes src/ext/PowerShell/wixext/PSCompiler.cs | 285 +++++++++++++++++++++ src/ext/PowerShell/wixext/PSErrors.cs | 30 +++ src/ext/PowerShell/wixext/PSExtensionData.cs | 30 +++ src/ext/PowerShell/wixext/PSWarnings.cs | 30 +++ .../wixext/PowerShellExtensionFactory.cs | 17 ++ .../wixext/WixToolset.PowerShell.wixext.csproj | 30 +++ .../wixext/WixToolset.PowerShell.wixext.targets | 11 + src/ext/PowerShell/wixlib/PSExtension.wxs | 12 + src/ext/PowerShell/wixlib/powershell.wixproj | 11 + src/ext/global.json | 5 + 26 files changed, 796 insertions(+) create mode 100644 src/ext/PowerShell/CSharp.Build.props create mode 100644 src/ext/PowerShell/Directory.Build.props create mode 100644 src/ext/PowerShell/Directory.Build.targets create mode 100644 src/ext/PowerShell/FindLocalWix.props create mode 100644 src/ext/PowerShell/PowerShell.wixext.sln create mode 100644 src/ext/PowerShell/README.md create mode 100644 src/ext/PowerShell/appveyor.cmd create mode 100644 src/ext/PowerShell/appveyor.yml create mode 100644 src/ext/PowerShell/nuget.config create mode 100644 src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs create mode 100644 src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.en-us.wxl create mode 100644 src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.wxs create mode 100644 src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/PackageComponents.wxs create mode 100644 src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/example.txt create mode 100644 src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj create mode 100644 src/ext/PowerShell/wix.snk create mode 100644 src/ext/PowerShell/wixext/PSCompiler.cs create mode 100644 src/ext/PowerShell/wixext/PSErrors.cs create mode 100644 src/ext/PowerShell/wixext/PSExtensionData.cs create mode 100644 src/ext/PowerShell/wixext/PSWarnings.cs create mode 100644 src/ext/PowerShell/wixext/PowerShellExtensionFactory.cs create mode 100644 src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.csproj create mode 100644 src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.targets create mode 100644 src/ext/PowerShell/wixlib/PSExtension.wxs create mode 100644 src/ext/PowerShell/wixlib/powershell.wixproj create mode 100644 src/ext/global.json (limited to 'src/ext') diff --git a/src/ext/PowerShell/CSharp.Build.props b/src/ext/PowerShell/CSharp.Build.props new file mode 100644 index 00000000..b12f4c6e --- /dev/null +++ b/src/ext/PowerShell/CSharp.Build.props @@ -0,0 +1,11 @@ + + + + + true + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk)) + + diff --git a/src/ext/PowerShell/Directory.Build.props b/src/ext/PowerShell/Directory.Build.props new file mode 100644 index 00000000..f83cc154 --- /dev/null +++ b/src/ext/PowerShell/Directory.Build.props @@ -0,0 +1,29 @@ + + + + + + Debug + false + MSB3246 + + $(MSBuildProjectName) + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) + $(BaseOutputPath)obj\$(ProjectName)\ + $(BaseOutputPath)$(Configuration)\ + + WiX Toolset Team + WiX Toolset + Copyright (c) .NET Foundation and contributors. All rights reserved. + MS-RL + WiX Toolset + + + + + + + diff --git a/src/ext/PowerShell/Directory.Build.targets b/src/ext/PowerShell/Directory.Build.targets new file mode 100644 index 00000000..dac7452a --- /dev/null +++ b/src/ext/PowerShell/Directory.Build.targets @@ -0,0 +1,48 @@ + + + + + + + true + $(SolutionPath) + $(NCrunchOriginalSolutionPath) + + + + + + + $([System.IO.File]::ReadAllText($(TheSolutionPath))) + $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) + (?<="[PackageName]", ")(.*)(?=", ") + + + + + + %(Identity) + $(SolutionFileContent.Contains('\%(Identity).csproj')) + + + + + $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) + $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) + + + + + + + + + + + diff --git a/src/ext/PowerShell/FindLocalWix.props b/src/ext/PowerShell/FindLocalWix.props new file mode 100644 index 00000000..1666e4fe --- /dev/null +++ b/src/ext/PowerShell/FindLocalWix.props @@ -0,0 +1,8 @@ + + + + + + $(MSBuildThisFileDirectory)..\..\Tools\build\Debug\net461\wix.targets + + diff --git a/src/ext/PowerShell/PowerShell.wixext.sln b/src/ext/PowerShell/PowerShell.wixext.sln new file mode 100644 index 00000000..a036d47e --- /dev/null +++ b/src/ext/PowerShell/PowerShell.wixext.sln @@ -0,0 +1,63 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30611.23 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "powershell", "src\wixlib\powershell.wixproj", "{9D4CCDFC-840C-4D4E-A9B0-3D6015480645}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.PowerShell.wixext", "src\wixext\WixToolset.PowerShell.wixext.csproj", "{6F1482DF-1598-4D88-BDAA-B9D0E0242139}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.PowerShell", "src\test\WixToolsetTest.PowerShell\WixToolsetTest.PowerShell.csproj", "{BFD10109-F4F3-4530-BE3B-802342D411F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|Any CPU.Build.0 = Debug|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|x64.ActiveCfg = Debug|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|x86.ActiveCfg = Debug|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|x86.Build.0 = Debug|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|Any CPU.ActiveCfg = Release|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|Any CPU.Build.0 = Release|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|x64.ActiveCfg = Release|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|x86.ActiveCfg = Release|x86 + {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|x86.Build.0 = Release|x86 + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x64.ActiveCfg = Debug|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x64.Build.0 = Debug|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x86.ActiveCfg = Debug|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x86.Build.0 = Debug|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|Any CPU.Build.0 = Release|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x64.ActiveCfg = Release|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x64.Build.0 = Release|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x86.ActiveCfg = Release|Any CPU + {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x86.Build.0 = Release|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x64.ActiveCfg = Debug|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x64.Build.0 = Debug|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x86.ActiveCfg = Debug|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x86.Build.0 = Debug|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|Any CPU.Build.0 = Release|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x64.ActiveCfg = Release|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x64.Build.0 = Release|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x86.ActiveCfg = Release|Any CPU + {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {60A3EA0F-9313-47F8-BF6B-74478A57B577} + EndGlobalSection +EndGlobal diff --git a/src/ext/PowerShell/README.md b/src/ext/PowerShell/README.md new file mode 100644 index 00000000..6de236f7 --- /dev/null +++ b/src/ext/PowerShell/README.md @@ -0,0 +1,2 @@ +# PowerShell.wixext +WixToolset.PowerShell.wixext - PowerShell WiX Toolset Extension diff --git a/src/ext/PowerShell/appveyor.cmd b/src/ext/PowerShell/appveyor.cmd new file mode 100644 index 00000000..27d33a5d --- /dev/null +++ b/src/ext/PowerShell/appveyor.cmd @@ -0,0 +1,13 @@ +@setlocal +@pushd %~dp0 + +nuget restore + +msbuild -p:Configuration=Release -t:Restore + +msbuild -p:Configuration=Release src\test\WixToolsetTest.PowerShell\WixToolsetTest.PowerShell.csproj + +msbuild -p:Configuration=Release -t:Pack src\wixext\WixToolset.PowerShell.wixext.csproj + +@popd +@endlocal \ No newline at end of file diff --git a/src/ext/PowerShell/appveyor.yml b/src/ext/PowerShell/appveyor.yml new file mode 100644 index 00000000..7c686b04 --- /dev/null +++ b/src/ext/PowerShell/appveyor.yml @@ -0,0 +1,40 @@ +# 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. +# +# Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml +# then update all of the repos. + +branches: + only: + - master + - develop + +image: Visual Studio 2019 + +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_branch_with_pr: true +skip_tags: true + +artifacts: +- path: build\Release\**\*.nupkg + name: nuget + +notifications: +- provider: Slack + incoming_webhook: + secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA= diff --git a/src/ext/PowerShell/nuget.config b/src/ext/PowerShell/nuget.config new file mode 100644 index 00000000..f4f0704e --- /dev/null +++ b/src/ext/PowerShell/nuget.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs new file mode 100644 index 00000000..b2f27ecf --- /dev/null +++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs @@ -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 WixToolsetTest.PowerShell +{ + using WixBuildTools.TestSupport; + using WixToolset.Core.TestPackage; + using WixToolset.PowerShell; + using Xunit; + + public class PowerShellExtensionFixture + { + [Fact] + public void CantBuildUsingTypesFileWithoutSnapIn() + { + var folder = TestData.Get(@"TestData\TypesFile"); + var build = new Builder(folder, typeof(PowerShellExtensionFactory), new[] { folder }); + + WixRunnerResult wixRunnerResult = null; + var results = build.BuildAndQuery(args => { + wixRunnerResult = WixRunner.Execute(args); + }); + Assert.NotNull(wixRunnerResult); + Assert.Equal((int)PSErrors.Ids.NeitherIdSpecified, wixRunnerResult.ExitCode); + } + } +} diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.en-us.wxl b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.en-us.wxl new file mode 100644 index 00000000..38c12ac1 --- /dev/null +++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.en-us.wxl @@ -0,0 +1,11 @@ + + + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.wxs b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.wxs new file mode 100644 index 00000000..411893bc --- /dev/null +++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/PackageComponents.wxs b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/PackageComponents.wxs new file mode 100644 index 00000000..049f9a51 --- /dev/null +++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/PackageComponents.wxs @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/example.txt b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj new file mode 100644 index 00000000..69645fb7 --- /dev/null +++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj @@ -0,0 +1,41 @@ + + + + + + netcoreapp3.1 + false + + + + NU1701 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/PowerShell/wix.snk b/src/ext/PowerShell/wix.snk new file mode 100644 index 00000000..3908a66a Binary files /dev/null and b/src/ext/PowerShell/wix.snk differ diff --git a/src/ext/PowerShell/wixext/PSCompiler.cs b/src/ext/PowerShell/wixext/PSCompiler.cs new file mode 100644 index 00000000..37591282 --- /dev/null +++ b/src/ext/PowerShell/wixext/PSCompiler.cs @@ -0,0 +1,285 @@ +// 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.PowerShell +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Extensibility; + + /// + /// The compiler for the WiX Toolset PowerShell Extension. + /// + public sealed class PSCompiler : BaseCompilerExtension + { + private const string KeyFormat = @"SOFTWARE\Microsoft\PowerShell\{0}\PowerShellSnapIns\{1}"; + private const string VarPrefix = "PSVersionMajor"; + + public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/powershell"; + + /// + /// Processes an element for the Compiler. + /// + /// Source line number for the parent element. + /// Parent element of element to process. + /// Element to process. + /// Extra information about the context in which this element is being parsed. + public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) + { + switch (parentElement.Name.LocalName) + { + case "File": + var fileId = context["FileId"]; + var componentId = context["ComponentId"]; + + switch (element.Name.LocalName) + { + case "FormatsFile": + this.ParseExtensionsFile(intermediate, section, element, "Formats", fileId, componentId); + break; + + case "SnapIn": + this.ParseSnapInElement(intermediate, section, element, fileId, componentId); + break; + + case "TypesFile": + this.ParseExtensionsFile(intermediate, section, element, "Types", fileId, componentId); + break; + + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + } + + /// + /// Parses a SnapIn element. + /// + /// Element to parse. + /// Identifier for parent file. + /// Identifier for parent component. + private void ParseSnapInElement(Intermediate intermediate, IntermediateSection section, XElement node, string fileId, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); + string id = null; + string customSnapInType = null; + string description = null; + string descriptionIndirect = null; + var requiredPowerShellVersion = CompilerConstants.IllegalVersion; + string vendor = null; + string vendorIndirect = null; + string version = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + break; + + case "CustomSnapInType": + customSnapInType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + case "Description": + description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + case "DescriptionIndirect": + descriptionIndirect = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + case "RequiredPowerShellVersion": + var ver = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib); + requiredPowerShellVersion = new Version(ver); + break; + + case "Vendor": + vendor = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + case "VendorIndirect": + vendorIndirect = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + case "Version": + version = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib); + break; + + default: + this.ParseHelper.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); + } + } + + if (null == id) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + // Default to require PowerShell 1.0. + if (CompilerConstants.IllegalVersion == requiredPowerShellVersion) + { + requiredPowerShellVersion = new Version(1, 0); + } + + // If the snap-in version isn't explicitly specified, get it + // from the assembly version at bind time. + if (null == version) + { + version = String.Format("!(bind.assemblyVersion.{0})", fileId); + } + + foreach (var child in node.Elements()) + { + if (this.Namespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "FormatsFile": + this.ParseExtensionsFile(intermediate, section, child, "Formats", id, componentId); + break; + case "TypesFile": + this.ParseExtensionsFile(intermediate, section, child, "Types", id, componentId); + break; + default: + this.ParseHelper.UnexpectedElement(node, child); + break; + } + } + else + { + this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, node, child); + } + } + + // Get the major part of the required PowerShell version which is + // needed for the registry key, and put that into a WiX variable + // for use in Formats and Types files. PowerShell v2 still uses 1. + var major = (2 == requiredPowerShellVersion.Major) ? 1 : requiredPowerShellVersion.Major; + + var variableId = new Identifier(AccessModifier.Global, String.Format(CultureInfo.InvariantCulture, "{0}_{1}", VarPrefix, id)); + section.AddSymbol(new WixVariableSymbol(sourceLineNumbers, variableId) + { + Value = major.ToString(CultureInfo.InvariantCulture), + Overridable = false, + }); + + var registryRoot = RegistryRootType.LocalMachine; // HKLM + var registryKey = String.Format(CultureInfo.InvariantCulture, KeyFormat, major, id); + + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "ApplicationBase", String.Format(CultureInfo.InvariantCulture, "[${0}]", componentId), componentId, false); + + // set the assembly name automatically when binding. + // processorArchitecture is not handled correctly by PowerShell v1.0 + // so format the assembly name explicitly. + var assemblyName = String.Format(CultureInfo.InvariantCulture, "!(bind.assemblyName.{0}), Version=!(bind.assemblyVersion.{0}), Culture=!(bind.assemblyCulture.{0}), PublicKeyToken=!(bind.assemblyPublicKeyToken.{0})", fileId); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "AssemblyName", assemblyName, componentId, false); + + if (null != customSnapInType) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "CustomPSSnapInType", customSnapInType, componentId, false); + } + + if (null != description) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "Description", description, componentId, false); + } + + if (null != descriptionIndirect) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "DescriptionIndirect", descriptionIndirect, componentId, false); + } + + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "ModuleName", String.Format(CultureInfo.InvariantCulture, "[#{0}]", fileId), componentId, false); + + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "PowerShellVersion", requiredPowerShellVersion.ToString(2), componentId, false); + + if (null != vendor) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "Vendor", vendor, componentId, false); + } + + if (null != vendorIndirect) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "VendorIndirect", vendorIndirect, componentId, false); + } + + if (null != version) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "Version", version, componentId, false); + } + } + + /// + /// Parses a FormatsFile and TypesFile element. + /// + /// Element to parse. + /// Registry value name. + /// Idendifier for parent file or snap-in. + /// Identifier for parent component. + private void ParseExtensionsFile(Intermediate intermediate, IntermediateSection section, XElement node, string valueName, string id, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); + string fileId = null; + string snapIn = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "FileId": + fileId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + snapIn = id; + break; + + case "SnapIn": + fileId = id; + snapIn = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + default: + this.ParseHelper.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); + } + } + + if (null == fileId && null == snapIn) + { + this.Messaging.Write(PSErrors.NeitherIdSpecified(sourceLineNumbers, valueName)); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); + + var registryRoot = RegistryRootType.LocalMachine; // HKLM + var registryKey = String.Format(CultureInfo.InvariantCulture, KeyFormat, String.Format(CultureInfo.InvariantCulture, "!(wix.{0}_{1})", VarPrefix, snapIn), snapIn); + + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.File, fileId); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, valueName, String.Format(CultureInfo.InvariantCulture, "[~][#{0}]", fileId), componentId, false); + } + } +} diff --git a/src/ext/PowerShell/wixext/PSErrors.cs b/src/ext/PowerShell/wixext/PSErrors.cs new file mode 100644 index 00000000..704cf5cd --- /dev/null +++ b/src/ext/PowerShell/wixext/PSErrors.cs @@ -0,0 +1,30 @@ +// 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.PowerShell +{ + using System.Resources; + using WixToolset.Data; + + public static class PSErrors + { + public static Message NeitherIdSpecified(SourceLineNumber sourceLineNumbers, string element) + { + return Message(sourceLineNumbers, Ids.NeitherIdSpecified, "Either the {0}/@FileId attribute must be specified if nested under a SnapIn element, or the {0}/@SnapIn attribute must be specified if nested under under a File element.", element); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args); + } + + public enum Ids + { + NeitherIdSpecified = 5301, + } + } +} diff --git a/src/ext/PowerShell/wixext/PSExtensionData.cs b/src/ext/PowerShell/wixext/PSExtensionData.cs new file mode 100644 index 00000000..66627942 --- /dev/null +++ b/src/ext/PowerShell/wixext/PSExtensionData.cs @@ -0,0 +1,30 @@ +// 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.PowerShell +{ + using WixToolset.Data; + using WixToolset.Extensibility; + + /// + /// The WiX Toolset PowerShell Extension. + /// + public sealed class PSExtensionData : BaseExtensionData + { + /// + /// Gets the default culture. + /// + /// The default culture. + public override string DefaultCulture => "en-US"; + + public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) + { + return Intermediate.Load(typeof(PSExtensionData).Assembly, "WixToolset.PowerShell.powershell.wixlib", symbolDefinitions); + } + + public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) + { + symbolDefinition = null; + return symbolDefinition != null; + } + } +} diff --git a/src/ext/PowerShell/wixext/PSWarnings.cs b/src/ext/PowerShell/wixext/PSWarnings.cs new file mode 100644 index 00000000..9be14948 --- /dev/null +++ b/src/ext/PowerShell/wixext/PSWarnings.cs @@ -0,0 +1,30 @@ +// 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.PowerShell +{ + using System.Resources; + using WixToolset.Data; + + public static class PSWarnings + { + public static Message DeprecatedAssemblyNameAttribute(SourceLineNumber sourceLineNumbers) + { + return Message(sourceLineNumbers, Ids.DeprecatedAssemblyNameAttribute, "The SnapIn/@AssemblyName attribute is deprecated. It is assigned automatically."); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, resourceManager, resourceName, args); + } + + public enum Ids + { + DeprecatedAssemblyNameAttribute = 5350, + } + } +} diff --git a/src/ext/PowerShell/wixext/PowerShellExtensionFactory.cs b/src/ext/PowerShell/wixext/PowerShellExtensionFactory.cs new file mode 100644 index 00000000..44f836e0 --- /dev/null +++ b/src/ext/PowerShell/wixext/PowerShellExtensionFactory.cs @@ -0,0 +1,17 @@ +// 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.PowerShell +{ + using System; + using System.Collections.Generic; + using WixToolset.Extensibility; + + public class PowerShellExtensionFactory : BaseExtensionFactory + { + protected override IReadOnlyCollection ExtensionTypes => new[] + { + typeof(PSCompiler), + typeof(PSExtensionData), + }; + } +} diff --git a/src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.csproj b/src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.csproj new file mode 100644 index 00000000..a89a574c --- /dev/null +++ b/src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.csproj @@ -0,0 +1,30 @@ + + + + + + netstandard2.0 + WixToolset.PowerShell + WiX Toolset PowerShell Extension + WiX Toolset PowerShell Extension + true + build + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.targets b/src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.targets new file mode 100644 index 00000000..bf06e1e4 --- /dev/null +++ b/src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.targets @@ -0,0 +1,11 @@ + + + + + + $(MSBuildThisFileDirectory)..\tools\WixToolset.PowerShell.wixext.dll + + + + + diff --git a/src/ext/PowerShell/wixlib/PSExtension.wxs b/src/ext/PowerShell/wixlib/PSExtension.wxs new file mode 100644 index 00000000..a1f16ee6 --- /dev/null +++ b/src/ext/PowerShell/wixlib/PSExtension.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/ext/PowerShell/wixlib/powershell.wixproj b/src/ext/PowerShell/wixlib/powershell.wixproj new file mode 100644 index 00000000..6d6b413b --- /dev/null +++ b/src/ext/PowerShell/wixlib/powershell.wixproj @@ -0,0 +1,11 @@ + + + + Library + true + + + + + + diff --git a/src/ext/global.json b/src/ext/global.json new file mode 100644 index 00000000..23dd3fa6 --- /dev/null +++ b/src/ext/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "WixToolset.Sdk": "4.0.0-build-0211" + } +} -- cgit v1.2.3-55-g6feb