aboutsummaryrefslogtreecommitdiff
path: root/src/ext
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-11 08:07:37 -0700
committerRob Mensching <rob@firegiant.com>2021-05-11 08:07:37 -0700
commit5b63db920c207d7115ff8f9ea19f36944766db7a (patch)
tree6f51a90276c18c36c4027784901b9633c8de2567 /src/ext
parent3ae536eb53fe0cc9bbcb1aeb0cd88c89f4f3e2cc (diff)
parent59765d27eb205b7b62a5057cfb631caee97f0af6 (diff)
downloadwix-5b63db920c207d7115ff8f9ea19f36944766db7a.tar.gz
wix-5b63db920c207d7115ff8f9ea19f36944766db7a.tar.bz2
wix-5b63db920c207d7115ff8f9ea19f36944766db7a.zip
Merge PowerShell.wixext
Diffstat (limited to 'src/ext')
-rw-r--r--src/ext/PowerShell/CSharp.Build.props11
-rw-r--r--src/ext/PowerShell/Directory.Build.props29
-rw-r--r--src/ext/PowerShell/Directory.Build.targets48
-rw-r--r--src/ext/PowerShell/FindLocalWix.props8
-rw-r--r--src/ext/PowerShell/PowerShell.wixext.sln63
-rw-r--r--src/ext/PowerShell/README.md2
-rw-r--r--src/ext/PowerShell/appveyor.cmd13
-rw-r--r--src/ext/PowerShell/appveyor.yml40
-rw-r--r--src/ext/PowerShell/nuget.config14
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs26
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.en-us.wxl11
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/Package.wxs15
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/PackageComponents.wxs13
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/TestData/TypesFile/example.txt1
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj41
-rw-r--r--src/ext/PowerShell/wix.snkbin0 -> 596 bytes
-rw-r--r--src/ext/PowerShell/wixext/PSCompiler.cs285
-rw-r--r--src/ext/PowerShell/wixext/PSErrors.cs30
-rw-r--r--src/ext/PowerShell/wixext/PSExtensionData.cs30
-rw-r--r--src/ext/PowerShell/wixext/PSWarnings.cs30
-rw-r--r--src/ext/PowerShell/wixext/PowerShellExtensionFactory.cs17
-rw-r--r--src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.csproj30
-rw-r--r--src/ext/PowerShell/wixext/WixToolset.PowerShell.wixext.targets11
-rw-r--r--src/ext/PowerShell/wixlib/PSExtension.wxs12
-rw-r--r--src/ext/PowerShell/wixlib/powershell.wixproj11
25 files changed, 791 insertions, 0 deletions
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 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2<!--
3 Do NOT modify this file. Update the canonical version in Home\repo-template\src\CSharp.Build.props
4 then update all of the repos.
5-->
6<Project>
7 <PropertyGroup>
8 <SignAssembly>true</SignAssembly>
9 <AssemblyOriginatorKeyFile>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk))</AssemblyOriginatorKeyFile>
10 </PropertyGroup>
11</Project>
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3<!--
4 Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.props
5 then update all of the repos.
6-->
7<Project>
8 <PropertyGroup>
9 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
10 <EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink>
11 <MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages>
12
13 <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName>
14 <BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath>
15 <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(ProjectName)\</BaseIntermediateOutputPath>
16 <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
17
18 <Authors>WiX Toolset Team</Authors>
19 <Company>WiX Toolset</Company>
20 <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright>
21 <PackageLicenseExpression>MS-RL</PackageLicenseExpression>
22 <Product>WiX Toolset</Product>
23 </PropertyGroup>
24
25 <Import Project="CSharp.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.csproj' and Exists('CSharp.Build.props') " />
26 <Import Project="Cpp.Build.props" Condition=" Exists('Cpp.Build.props') And '$(MSBuildProjectExtension)'=='.vcxproj' " />
27 <Import Project="Wix.Build.props" Condition=" Exists('Wix.Build.props') And '$(MSBuildProjectExtension)'=='.wixproj' " />
28 <Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " />
29</Project>
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3<!--
4 Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.targets
5 then update all of the repos.
6-->
7<!--
8 Replace PackageReferences with ProjectReferences when the projects can be found in .sln.
9 See the original here: https://github.com/dotnet/sdk/issues/1151#issuecomment-385133284
10-->
11<Project>
12 <PropertyGroup>
13 <ReplacePackageReferences>true</ReplacePackageReferences>
14 <TheSolutionPath Condition=" '$(NCrunch)'=='' ">$(SolutionPath)</TheSolutionPath>
15 <TheSolutionPath Condition=" '$(NCrunch)'=='1' ">$(NCrunchOriginalSolutionPath)</TheSolutionPath>
16 </PropertyGroup>
17
18 <Choose>
19 <When Condition="$(ReplacePackageReferences) AND '$(TheSolutionPath)' != '' AND '$(TheSolutionPath)' != '*undefined*' AND Exists('$(TheSolutionPath)')">
20
21 <PropertyGroup>
22 <SolutionFileContent>$([System.IO.File]::ReadAllText($(TheSolutionPath)))</SolutionFileContent>
23 <SmartSolutionDir>$([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) ))</SmartSolutionDir>
24 <RegexPattern>(?&lt;="[PackageName]", ")(.*)(?=", ")</RegexPattern>
25 </PropertyGroup>
26
27 <ItemGroup>
28 <!-- Keep the identity of the PackageReference -->
29 <SmartPackageReference Include="@(PackageReference)">
30 <PackageName>%(Identity)</PackageName>
31 <InSolution>$(SolutionFileContent.Contains('\%(Identity).csproj'))</InSolution>
32 </SmartPackageReference>
33
34 <!-- Filter them by mapping them to another ItemGroup using the WithMetadataValue item function -->
35 <PackageInSolution Include="@(SmartPackageReference->WithMetadataValue('InSolution', True))">
36 <Pattern>$(RegexPattern.Replace('[PackageName]','%(PackageName)') )</Pattern>
37 <SmartPath>$([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)'))</SmartPath>
38 </PackageInSolution>
39
40 <ProjectReference Include="@(PackageInSolution->'$(SmartSolutionDir)\%(SmartPath)' )"/>
41
42 <!-- Remove the package references that are now referenced as projects -->
43 <PackageReference Remove="@(PackageInSolution->'%(PackageName)' )"/>
44 </ItemGroup>
45
46 </When>
47 </Choose>
48</Project>
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <PropertyGroup>
6 <WixTargetsPath Condition=" '$(Configuration)' == 'Debug' And Exists('$(MSBuildThisFileDirectory)..\..\Tools\README.md') And Exists('$(MSBuildThisFileDirectory)..\..\Tools\build\Debug\net461\wix.targets') ">$(MSBuildThisFileDirectory)..\..\Tools\build\Debug\net461\wix.targets</WixTargetsPath>
7 </PropertyGroup>
8</Project>
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 @@
1
2Microsoft Visual Studio Solution File, Format Version 12.00
3# Visual Studio Version 16
4VisualStudioVersion = 16.0.30611.23
5MinimumVisualStudioVersion = 15.0.26124.0
6Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "powershell", "src\wixlib\powershell.wixproj", "{9D4CCDFC-840C-4D4E-A9B0-3D6015480645}"
7EndProject
8Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.PowerShell.wixext", "src\wixext\WixToolset.PowerShell.wixext.csproj", "{6F1482DF-1598-4D88-BDAA-B9D0E0242139}"
9EndProject
10Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.PowerShell", "src\test\WixToolsetTest.PowerShell\WixToolsetTest.PowerShell.csproj", "{BFD10109-F4F3-4530-BE3B-802342D411F7}"
11EndProject
12Global
13 GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 Debug|Any CPU = Debug|Any CPU
15 Debug|x64 = Debug|x64
16 Debug|x86 = Debug|x86
17 Release|Any CPU = Release|Any CPU
18 Release|x64 = Release|x64
19 Release|x86 = Release|x86
20 EndGlobalSection
21 GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|Any CPU.ActiveCfg = Debug|x86
23 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|Any CPU.Build.0 = Debug|x86
24 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|x64.ActiveCfg = Debug|x86
25 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|x86.ActiveCfg = Debug|x86
26 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Debug|x86.Build.0 = Debug|x86
27 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|Any CPU.ActiveCfg = Release|x86
28 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|Any CPU.Build.0 = Release|x86
29 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|x64.ActiveCfg = Release|x86
30 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|x86.ActiveCfg = Release|x86
31 {9D4CCDFC-840C-4D4E-A9B0-3D6015480645}.Release|x86.Build.0 = Release|x86
32 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x64.ActiveCfg = Debug|Any CPU
35 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x64.Build.0 = Debug|Any CPU
36 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x86.ActiveCfg = Debug|Any CPU
37 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Debug|x86.Build.0 = Debug|Any CPU
38 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|Any CPU.Build.0 = Release|Any CPU
40 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x64.ActiveCfg = Release|Any CPU
41 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x64.Build.0 = Release|Any CPU
42 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x86.ActiveCfg = Release|Any CPU
43 {6F1482DF-1598-4D88-BDAA-B9D0E0242139}.Release|x86.Build.0 = Release|Any CPU
44 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x64.ActiveCfg = Debug|Any CPU
47 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x64.Build.0 = Debug|Any CPU
48 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x86.ActiveCfg = Debug|Any CPU
49 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Debug|x86.Build.0 = Debug|Any CPU
50 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|Any CPU.Build.0 = Release|Any CPU
52 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x64.ActiveCfg = Release|Any CPU
53 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x64.Build.0 = Release|Any CPU
54 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x86.ActiveCfg = Release|Any CPU
55 {BFD10109-F4F3-4530-BE3B-802342D411F7}.Release|x86.Build.0 = Release|Any CPU
56 EndGlobalSection
57 GlobalSection(SolutionProperties) = preSolution
58 HideSolutionNode = FALSE
59 EndGlobalSection
60 GlobalSection(ExtensibilityGlobals) = postSolution
61 SolutionGuid = {60A3EA0F-9313-47F8-BF6B-74478A57B577}
62 EndGlobalSection
63EndGlobal
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 @@
1# PowerShell.wixext
2WixToolset.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 @@
1@setlocal
2@pushd %~dp0
3
4nuget restore
5
6msbuild -p:Configuration=Release -t:Restore
7
8msbuild -p:Configuration=Release src\test\WixToolsetTest.PowerShell\WixToolsetTest.PowerShell.csproj
9
10msbuild -p:Configuration=Release -t:Pack src\wixext\WixToolset.PowerShell.wixext.csproj
11
12@popd
13@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 @@
1# Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2#
3# Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml
4# then update all of the repos.
5
6branches:
7 only:
8 - master
9 - develop
10
11image: Visual Studio 2019
12
13version: 0.0.0.{build}
14configuration: Release
15
16environment:
17 DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
18 DOTNET_CLI_TELEMETRY_OPTOUT: 1
19 NUGET_XMLDOC_MODE: skip
20
21build_script:
22 - appveyor.cmd
23
24pull_requests:
25 do_not_increment_build_number: true
26
27nuget:
28 disable_publish_on_pr: true
29
30skip_branch_with_pr: true
31skip_tags: true
32
33artifacts:
34- path: build\Release\**\*.nupkg
35 name: nuget
36
37notifications:
38- provider: Slack
39 incoming_webhook:
40 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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<configuration>
3 <packageSources>
4 <clear />
5 <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" />
6 <add key="wixtoolset-extensibility" value="https://ci.appveyor.com/nuget/wixtoolset-extensibility" />
7 <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" />
8 <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" />
9 <add key="wixtoolset-dtf" value="https://ci.appveyor.com/nuget/wixtoolset-dtf" />
10 <add key="wixtoolset-tools" value="https://ci.appveyor.com/nuget/wixtoolset-tools" />
11 <add key="wixbuildtools" value="https://ci.appveyor.com/nuget/wixbuildtools" />
12 <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
13 </packageSources>
14</configuration> \ 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 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolsetTest.PowerShell
4{
5 using WixBuildTools.TestSupport;
6 using WixToolset.Core.TestPackage;
7 using WixToolset.PowerShell;
8 using Xunit;
9
10 public class PowerShellExtensionFixture
11 {
12 [Fact]
13 public void CantBuildUsingTypesFileWithoutSnapIn()
14 {
15 var folder = TestData.Get(@"TestData\TypesFile");
16 var build = new Builder(folder, typeof(PowerShellExtensionFactory), new[] { folder });
17
18 WixRunnerResult wixRunnerResult = null;
19 var results = build.BuildAndQuery(args => {
20 wixRunnerResult = WixRunner.Execute(args);
21 });
22 Assert.NotNull(wixRunnerResult);
23 Assert.Equal((int)PSErrors.Ids.NeitherIdSpecified, wixRunnerResult.ExitCode);
24 }
25 }
26}
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4This file contains the declaration of all the localizable strings.
5-->
6<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
7
8 <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
9 <String Id="FeatureTitle">MsiPackage</String>
10
11</WixLocalization>
diff --git a/src/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 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
5 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
6 <ComponentGroupRef Id="ProductComponents" />
7 </Feature>
8 </Package>
9
10 <Fragment>
11 <StandardDirectory Id="ProgramFilesFolder">
12 <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
13 </StandardDirectory>
14 </Fragment>
15</Wix>
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3 xmlns:powershell="http://wixtoolset.org/schemas/v4/wxs/powershell">
4 <Fragment>
5 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
6 <Component>
7 <File Source="example.txt">
8 <powershell:TypesFile />
9 </File>
10 </Component>
11 </ComponentGroup>
12 </Fragment>
13</Wix>
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netcoreapp3.1</TargetFramework>
7 <IsPackable>false</IsPackable>
8 </PropertyGroup>
9
10 <PropertyGroup>
11 <NoWarn>NU1701</NoWarn>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Content Include="TestData\TypesFile\example.txt" CopyToOutputDirectory="PreserveNewest" />
16 <Content Include="TestData\TypesFile\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
17 <Content Include="TestData\TypesFile\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
18 <Content Include="TestData\TypesFile\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
19 </ItemGroup>
20
21 <ItemGroup>
22 <ProjectReference Include="..\..\wixext\WixToolset.Powershell.wixext.csproj" />
23 </ItemGroup>
24
25 <ItemGroup>
26 <PackageReference Include="WixToolset.Core" Version="4.0.*" />
27 <PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" />
28 <PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" />
29 <PackageReference Include="WixToolset.Core.TestPackage" Version="4.0.*" />
30 </ItemGroup>
31
32 <ItemGroup>
33 <PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" />
34 </ItemGroup>
35
36 <ItemGroup>
37 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
38 <PackageReference Include="xunit" Version="2.4.1" />
39 <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="All" />
40 </ItemGroup>
41</Project>
diff --git a/src/ext/PowerShell/wix.snk b/src/ext/PowerShell/wix.snk
new file mode 100644
index 00000000..3908a66a
--- /dev/null
+++ b/src/ext/PowerShell/wix.snk
Binary files 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 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.PowerShell
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Xml.Linq;
9 using WixToolset.Data;
10 using WixToolset.Data.Symbols;
11 using WixToolset.Extensibility;
12
13 /// <summary>
14 /// The compiler for the WiX Toolset PowerShell Extension.
15 /// </summary>
16 public sealed class PSCompiler : BaseCompilerExtension
17 {
18 private const string KeyFormat = @"SOFTWARE\Microsoft\PowerShell\{0}\PowerShellSnapIns\{1}";
19 private const string VarPrefix = "PSVersionMajor";
20
21 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/powershell";
22
23 /// <summary>
24 /// Processes an element for the Compiler.
25 /// </summary>
26 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
27 /// <param name="parentElement">Parent element of element to process.</param>
28 /// <param name="element">Element to process.</param>
29 /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
30 public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
31 {
32 switch (parentElement.Name.LocalName)
33 {
34 case "File":
35 var fileId = context["FileId"];
36 var componentId = context["ComponentId"];
37
38 switch (element.Name.LocalName)
39 {
40 case "FormatsFile":
41 this.ParseExtensionsFile(intermediate, section, element, "Formats", fileId, componentId);
42 break;
43
44 case "SnapIn":
45 this.ParseSnapInElement(intermediate, section, element, fileId, componentId);
46 break;
47
48 case "TypesFile":
49 this.ParseExtensionsFile(intermediate, section, element, "Types", fileId, componentId);
50 break;
51
52 default:
53 this.ParseHelper.UnexpectedElement(parentElement, element);
54 break;
55 }
56 break;
57
58 default:
59 this.ParseHelper.UnexpectedElement(parentElement, element);
60 break;
61 }
62 }
63
64 /// <summary>
65 /// Parses a SnapIn element.
66 /// </summary>
67 /// <param name="node">Element to parse.</param>
68 /// <param name="fileId">Identifier for parent file.</param>
69 /// <param name="componentId">Identifier for parent component.</param>
70 private void ParseSnapInElement(Intermediate intermediate, IntermediateSection section, XElement node, string fileId, string componentId)
71 {
72 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node);
73 string id = null;
74 string customSnapInType = null;
75 string description = null;
76 string descriptionIndirect = null;
77 var requiredPowerShellVersion = CompilerConstants.IllegalVersion;
78 string vendor = null;
79 string vendorIndirect = null;
80 string version = null;
81
82 foreach (var attrib in node.Attributes())
83 {
84 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
85 {
86 switch (attrib.Name.LocalName)
87 {
88 case "Id":
89 id = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
90 break;
91
92 case "CustomSnapInType":
93 customSnapInType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
94 break;
95
96 case "Description":
97 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
98 break;
99
100 case "DescriptionIndirect":
101 descriptionIndirect = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
102 break;
103
104 case "RequiredPowerShellVersion":
105 var ver = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib);
106 requiredPowerShellVersion = new Version(ver);
107 break;
108
109 case "Vendor":
110 vendor = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
111 break;
112
113 case "VendorIndirect":
114 vendorIndirect = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
115 break;
116
117 case "Version":
118 version = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib);
119 break;
120
121 default:
122 this.ParseHelper.UnexpectedAttribute(node, attrib);
123 break;
124 }
125 }
126 else
127 {
128 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib);
129 }
130 }
131
132 if (null == id)
133 {
134 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
135 }
136
137 // Default to require PowerShell 1.0.
138 if (CompilerConstants.IllegalVersion == requiredPowerShellVersion)
139 {
140 requiredPowerShellVersion = new Version(1, 0);
141 }
142
143 // If the snap-in version isn't explicitly specified, get it
144 // from the assembly version at bind time.
145 if (null == version)
146 {
147 version = String.Format("!(bind.assemblyVersion.{0})", fileId);
148 }
149
150 foreach (var child in node.Elements())
151 {
152 if (this.Namespace == child.Name.Namespace)
153 {
154 switch (child.Name.LocalName)
155 {
156 case "FormatsFile":
157 this.ParseExtensionsFile(intermediate, section, child, "Formats", id, componentId);
158 break;
159 case "TypesFile":
160 this.ParseExtensionsFile(intermediate, section, child, "Types", id, componentId);
161 break;
162 default:
163 this.ParseHelper.UnexpectedElement(node, child);
164 break;
165 }
166 }
167 else
168 {
169 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, node, child);
170 }
171 }
172
173 // Get the major part of the required PowerShell version which is
174 // needed for the registry key, and put that into a WiX variable
175 // for use in Formats and Types files. PowerShell v2 still uses 1.
176 var major = (2 == requiredPowerShellVersion.Major) ? 1 : requiredPowerShellVersion.Major;
177
178 var variableId = new Identifier(AccessModifier.Global, String.Format(CultureInfo.InvariantCulture, "{0}_{1}", VarPrefix, id));
179 section.AddSymbol(new WixVariableSymbol(sourceLineNumbers, variableId)
180 {
181 Value = major.ToString(CultureInfo.InvariantCulture),
182 Overridable = false,
183 });
184
185 var registryRoot = RegistryRootType.LocalMachine; // HKLM
186 var registryKey = String.Format(CultureInfo.InvariantCulture, KeyFormat, major, id);
187
188 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "ApplicationBase", String.Format(CultureInfo.InvariantCulture, "[${0}]", componentId), componentId, false);
189
190 // set the assembly name automatically when binding.
191 // processorArchitecture is not handled correctly by PowerShell v1.0
192 // so format the assembly name explicitly.
193 var assemblyName = String.Format(CultureInfo.InvariantCulture, "!(bind.assemblyName.{0}), Version=!(bind.assemblyVersion.{0}), Culture=!(bind.assemblyCulture.{0}), PublicKeyToken=!(bind.assemblyPublicKeyToken.{0})", fileId);
194 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "AssemblyName", assemblyName, componentId, false);
195
196 if (null != customSnapInType)
197 {
198 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "CustomPSSnapInType", customSnapInType, componentId, false);
199 }
200
201 if (null != description)
202 {
203 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "Description", description, componentId, false);
204 }
205
206 if (null != descriptionIndirect)
207 {
208 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "DescriptionIndirect", descriptionIndirect, componentId, false);
209 }
210
211 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "ModuleName", String.Format(CultureInfo.InvariantCulture, "[#{0}]", fileId), componentId, false);
212
213 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "PowerShellVersion", requiredPowerShellVersion.ToString(2), componentId, false);
214
215 if (null != vendor)
216 {
217 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "Vendor", vendor, componentId, false);
218 }
219
220 if (null != vendorIndirect)
221 {
222 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "VendorIndirect", vendorIndirect, componentId, false);
223 }
224
225 if (null != version)
226 {
227 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, "Version", version, componentId, false);
228 }
229 }
230
231 /// <summary>
232 /// Parses a FormatsFile and TypesFile element.
233 /// </summary>
234 /// <param name="node">Element to parse.</param>
235 /// <param name="valueName">Registry value name.</param>
236 /// <param name="id">Idendifier for parent file or snap-in.</param>
237 /// <param name="componentId">Identifier for parent component.</param>
238 private void ParseExtensionsFile(Intermediate intermediate, IntermediateSection section, XElement node, string valueName, string id, string componentId)
239 {
240 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node);
241 string fileId = null;
242 string snapIn = null;
243
244 foreach (var attrib in node.Attributes())
245 {
246 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
247 {
248 switch (attrib.Name.LocalName)
249 {
250 case "FileId":
251 fileId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
252 snapIn = id;
253 break;
254
255 case "SnapIn":
256 fileId = id;
257 snapIn = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
258 break;
259
260 default:
261 this.ParseHelper.UnexpectedAttribute(node, attrib);
262 break;
263 }
264 }
265 else
266 {
267 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib);
268 }
269 }
270
271 if (null == fileId && null == snapIn)
272 {
273 this.Messaging.Write(PSErrors.NeitherIdSpecified(sourceLineNumbers, valueName));
274 }
275
276 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node);
277
278 var registryRoot = RegistryRootType.LocalMachine; // HKLM
279 var registryKey = String.Format(CultureInfo.InvariantCulture, KeyFormat, String.Format(CultureInfo.InvariantCulture, "!(wix.{0}_{1})", VarPrefix, snapIn), snapIn);
280
281 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.File, fileId);
282 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, registryRoot, registryKey, valueName, String.Format(CultureInfo.InvariantCulture, "[~][#{0}]", fileId), componentId, false);
283 }
284 }
285}
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 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.PowerShell
4{
5 using System.Resources;
6 using WixToolset.Data;
7
8 public static class PSErrors
9 {
10 public static Message NeitherIdSpecified(SourceLineNumber sourceLineNumbers, string element)
11 {
12 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);
13 }
14
15 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
16 {
17 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
18 }
19
20 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
21 {
22 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
23 }
24
25 public enum Ids
26 {
27 NeitherIdSpecified = 5301,
28 }
29 }
30}
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 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.PowerShell
4{
5 using WixToolset.Data;
6 using WixToolset.Extensibility;
7
8 /// <summary>
9 /// The WiX Toolset PowerShell Extension.
10 /// </summary>
11 public sealed class PSExtensionData : BaseExtensionData
12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
20 {
21 return Intermediate.Load(typeof(PSExtensionData).Assembly, "WixToolset.PowerShell.powershell.wixlib", symbolDefinitions);
22 }
23
24 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
25 {
26 symbolDefinition = null;
27 return symbolDefinition != null;
28 }
29 }
30}
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 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.PowerShell
4{
5 using System.Resources;
6 using WixToolset.Data;
7
8 public static class PSWarnings
9 {
10 public static Message DeprecatedAssemblyNameAttribute(SourceLineNumber sourceLineNumbers)
11 {
12 return Message(sourceLineNumbers, Ids.DeprecatedAssemblyNameAttribute, "The SnapIn/@AssemblyName attribute is deprecated. It is assigned automatically.");
13 }
14
15 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
16 {
17 return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args);
18 }
19
20 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
21 {
22 return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, resourceManager, resourceName, args);
23 }
24
25 public enum Ids
26 {
27 DeprecatedAssemblyNameAttribute = 5350,
28 }
29 }
30}
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 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.PowerShell
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Extensibility;
8
9 public class PowerShellExtensionFactory : BaseExtensionFactory
10 {
11 protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
12 {
13 typeof(PSCompiler),
14 typeof(PSExtensionData),
15 };
16 }
17}
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netstandard2.0</TargetFramework>
7 <RootNamespace>WixToolset.PowerShell</RootNamespace>
8 <Description>WiX Toolset PowerShell Extension</Description>
9 <Title>WiX Toolset PowerShell Extension</Title>
10 <IsTool>true</IsTool>
11 <ContentTargetFolders>build</ContentTargetFolders>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Content Include="$(MSBuildThisFileName).targets" />
16 <EmbeddedResource Include="$(OutputPath)..\powershell.wixlib" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="all" />
21 </ItemGroup>
22
23 <ItemGroup>
24 <ProjectReference Include="..\wixlib\powershell.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " />
25 </ItemGroup>
26
27 <ItemGroup>
28 <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="all" />
29 </ItemGroup>
30</Project>
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 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
5 <PropertyGroup>
6 <WixToolsetPowerShellWixextPath Condition=" '$(WixToolsetPowerShellWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.PowerShell.wixext.dll</WixToolsetPowerShellWixextPath>
7 </PropertyGroup>
8 <ItemGroup>
9 <WixExtension Include="$(WixToolsetPowerShellWixextPath)" />
10 </ItemGroup>
11</Project>
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 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!-- 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. -->
3
4
5<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
6 <!-- Gets the version of PowerShell installed. v1 and v2 share this key. -->
7 <Fragment>
8 <Property Id="POWERSHELLVERSION" Secure="yes">
9 <RegistrySearch Id="PowerShellVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine" Name="PowerShellVersion" Type="raw" />
10 </Property>
11 </Fragment>
12</Wix>
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 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <OutputType>Library</OutputType>
5 <BindFiles>true</BindFiles>
6 </PropertyGroup>
7
8 <ItemGroup>
9 <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" />
10 </ItemGroup>
11</Project>