├── .gitattributes
├── .github
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ ├── codeql.yml
│ ├── main.yml
│ └── publish.yml
├── .gitignore
├── Create-Package.ps1
├── Directory.Build.props
├── GitVersion.yml
├── LICENSE.txt
├── MSRL-LICENSE.txt
├── NuGet
├── content
│ └── PowerShellWixExtension.DummyFile.txt
└── tools
│ ├── Install.ps1
│ ├── Remove.psm1
│ └── Uninstall.ps1
├── PowerShellActions
├── CustomAction.config
├── CustomAction.cs
├── IExitCode.cs
├── PowerShellActions.csproj
├── PowerShellTask.cs
├── Properties
│ └── AssemblyInfo.cs
├── WixHost.cs
├── WixHostRawUserInterface.cs
└── WixHostUserInterface.cs
├── PowerShellLibrary
├── Library.wxs
└── PowerShellLibrary.wixproj
├── PowerShellWixExtension.nuspec
├── PowerShellWixExtension.sln
├── PowerShellWixExtension.sln.DotSettings
├── PowerShellWixExtension
├── PowerShellCompilerExtension.cs
├── PowerShellWixExtension.cs
├── PowerShellWixExtension.csproj
├── PowerShellWixExtensionSchema.cs
├── PowerShellWixExtensionSchema.xsd
├── Properties
│ └── AssemblyInfo.cs
└── TableDefinitions.xml
├── Publish-Package.ps1
├── README.md
├── Settings.StyleCop
├── Tests
├── Pester.Tests.ps1
├── PowerShellWixInlineScriptTest
│ ├── PowerShellWixInlineScriptTest.wixproj
│ ├── Product.wxs
│ └── TextFile1.txt
└── PowerShellWixTest
│ ├── PowerShellWixTest.wixproj
│ ├── Product.wxs
│ ├── ProgressDlg.wxs
│ └── Test.ps1
├── tables.xsd
└── version.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Basic set up for three package managers
2 |
3 | version: 2
4 | updates:
5 |
6 | # Maintain dependencies for GitHub Actions
7 | - package-ecosystem: "github-actions"
8 | directory: "/"
9 | schedule:
10 | interval: "daily"
11 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name-template: 'v$RESOLVED_VERSION'
2 | tag-template: 'v$RESOLVED_VERSION'
3 |
4 | template: |
5 | ## What’s Changed
6 |
7 | $CHANGES
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "main" ]
17 | pull_request:
18 | branches: [ "main" ]
19 | schedule:
20 | - cron: '44 23 * * 6'
21 |
22 | jobs:
23 | analyze:
24 | name: Analyze (${{ matrix.language }})
25 | # Runner size impacts CodeQL analysis time. To learn more, please see:
26 | # - https://gh.io/recommended-hardware-resources-for-running-codeql
27 | # - https://gh.io/supported-runners-and-hardware-resources
28 | # - https://gh.io/using-larger-runners (GitHub.com only)
29 | # Consider using larger runners or machines with greater resources for possible analysis time improvements.
30 | runs-on: windows-2019
31 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
32 | permissions:
33 | # required for all workflows
34 | security-events: write
35 |
36 | # required to fetch internal or private CodeQL packs
37 | packages: read
38 |
39 | # only required for workflows in private repositories
40 | actions: read
41 | contents: read
42 |
43 | strategy:
44 | fail-fast: false
45 | matrix:
46 | include:
47 | - language: csharp
48 | build-mode: manual
49 | # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
50 | # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
51 | # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
52 | # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
53 | steps:
54 | - name: Checkout repository
55 | uses: actions/checkout@v4
56 |
57 | - name: Setup MSBuild.exe
58 | uses: microsoft/setup-msbuild@v2.0.0
59 |
60 | # Initializes the CodeQL tools for scanning.
61 | - name: Initialize CodeQL
62 | uses: github/codeql-action/init@v3
63 | with:
64 | languages: ${{ matrix.language }}
65 | build-mode: ${{ matrix.build-mode }}
66 | # If you wish to specify custom queries, you can do so here or in a config file.
67 | # By default, queries listed here will override any specified in a config file.
68 | # Prefix the list here with "+" to use these queries and those in the config file.
69 |
70 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
71 | # queries: security-extended,security-and-quality
72 |
73 | # If the analyze step fails for one of the languages you are analyzing with
74 | # "We were unable to automatically build your code", modify the matrix above
75 | # to set the build mode to "manual" for that language. Then modify this step
76 | # to build your code.
77 | # ℹ️ Command-line programs to run using the OS shell.
78 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
79 | - if: matrix.build-mode == 'manual'
80 | run: |
81 | nuget restore /p:NoGitVersioning=true
82 | msbuild PowerShellWixExtension.sln /p:NoGitVersioning=true
83 |
84 | - name: Perform CodeQL Analysis
85 | uses: github/codeql-action/analyze@v3
86 | with:
87 | category: "/language:${{matrix.language}}"
88 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 |
9 | jobs:
10 | update_release_draft:
11 | name: Update release draft
12 | runs-on: ubuntu-latest
13 | outputs:
14 | Release_Id: ${{ steps.create_release.outputs.id}}
15 | Release_name: ${{ steps.create_release.outputs.name}}
16 | Release_tag_name: ${{ steps.create_release.outputs.tag_name}}
17 | Release_body: ${{ steps.create_release.outputs.body}}
18 | Release_html_url: ${{ steps.create_release.outputs.html_url}}
19 | Release_upload_url: ${{ steps.create_release.outputs.upload_url}}
20 |
21 | permissions:
22 | contents: write
23 |
24 | steps:
25 | # - uses: GitHubSecurityLab/actions-permissions/monitor@v1
26 | # with:
27 | # config: ${{ vars.PERMISSIONS_CONFIG }}
28 |
29 | - name: Checkout
30 | uses: actions/checkout@v4
31 | with:
32 | fetch-depth: 0
33 |
34 | - name: Nerdbank.GitVersioning
35 | uses: dotnet/nbgv@v0.4.2
36 | with:
37 | # Defines ALL version variables as environment variables, with a "NBGV_" prefix.
38 | setAllVars: true
39 | # Defines a few common version variables as environment variables, with a "Git" prefix (e.g. GitBuildVersion, GitBuildVersionSimple, GitAssemblyInformationalVersion).
40 | setCommonVars: true
41 |
42 | - uses: release-drafter/release-drafter@v6
43 | if: github.ref == 'refs/heads/main' # Running this action only for main branch
44 | id: create_release
45 | env:
46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47 | with:
48 | version: ${{ env.NBGV_SemVer2 }}
49 |
50 | build:
51 | needs: [update_release_draft]
52 |
53 | runs-on: windows-2019
54 |
55 | permissions:
56 | checks: write
57 | contents: write
58 |
59 | env:
60 | Configuration: Release
61 | Release_body: ${{ needs.update_release_draft.outputs.Release_body }}
62 |
63 | steps:
64 | - name: Dump needs context
65 | env:
66 | NEEDS_CONTEXT: ${{ toJson(needs) }}
67 | run: echo "$NEEDS_CONTEXT"
68 |
69 | - name: Checkout
70 | uses: actions/checkout@v4
71 | with:
72 | fetch-depth: 0
73 |
74 | - name: Setup MSBuild.exe
75 | uses: microsoft/setup-msbuild@v2.0.0
76 |
77 | - name: NuGet Restore
78 | run: nuget restore
79 |
80 | - name: Build
81 | run: msbuild PowerShellWixExtension.sln
82 | # NBGV is run as part of the build, so actions after here have access to NBGV_ env variables.
83 |
84 | # For some reason, running msiexec from Pester doesn't work quite right.
85 | - name: msiexec
86 | run: |
87 | Start-Process msiexec.exe -Wait -ArgumentList "/i Tests\PowerShellWixInlineScriptTest\bin\Release\PowerShellWixInlineScriptTest.msi /q /liwearucmopvx ${{ github.workspace }}\inlinescript-install.log"
88 | Start-Process msiexec.exe -Wait -ArgumentList "/x Tests\PowerShellWixInlineScriptTest\bin\Release\PowerShellWixInlineScriptTest.msi /q /liwearucmopvx ${{ github.workspace }}\inlinescript-uninstall.log"
89 | Start-Process msiexec.exe -Wait -ArgumentList "/i Tests\PowerShellWixTest\bin\Release\PowerShellWixTest.msi /q /liwearucmopvx ${{ github.workspace }}\script-install.log"
90 | Start-Process msiexec.exe -Wait -ArgumentList "/x Tests\PowerShellWixTest\bin\Release\PowerShellWixTest.msi /q /liwearucmopvx ${{ github.workspace }}\script-uninstall.log"
91 |
92 | - name: Pester
93 | id: test_module
94 | uses: zyborg/pester-tests-report@v1
95 | with:
96 | include_paths: tests
97 | github_token: ${{ secrets.GITHUB_TOKEN }}
98 | tests_fail_step: true
99 |
100 | - uses: actions/upload-artifact@v4
101 | if: ${{ always() }}
102 | with:
103 | name: test logs
104 | path: ${{ github.workspace }}\**\*.log
105 |
106 | - name: Pack
107 | run: nuget pack .\PowerShellWixExtension.nuspec -Version "$env:NBGV_NuGetPackageVersion" -Properties "Configuration=$env:Configuration;releasenotes=$env:Release_body"
108 |
109 | - uses: actions/upload-artifact@v4
110 | with:
111 | name: nupkg
112 | path: ${{ github.workspace }}\PowerShellWixExtension.${{ env.NBGV_NuGetPackageVersion }}.nupkg
113 |
114 | - name: Remove existing release asset
115 | uses: flcdrg/remove-release-asset-action@v4
116 | if: github.ref == 'refs/heads/main' # Running this action only for main branch
117 | with:
118 | # The release id to remove asset from
119 | release_id: ${{ needs.update_release_draft.outputs.Release_Id }}
120 | # The name of the asset you want to remove
121 | asset_name: PowerShellWixExtension.nupkg
122 | env:
123 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
124 | continue-on-error: true
125 |
126 | - name: Upload Release Asset
127 | id: upload-release-asset
128 | uses: actions/upload-release-asset@v1
129 | if: github.ref == 'refs/heads/main' # Running this action only for master branch
130 | env:
131 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
132 | with:
133 | upload_url: ${{ needs.update_release_draft.outputs.Release_upload_url }}
134 | asset_path: ${{ github.workspace }}\PowerShellWixExtension.${{ env.NBGV_NuGetPackageVersion }}.nupkg
135 | asset_name: PowerShellWixExtension.nupkg
136 | asset_content_type: application/octet-stream
137 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 |
3 | on:
4 | release:
5 | types: # https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#release
6 | - published
7 |
8 | jobs:
9 | publish:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | # - uses: GitHubSecurityLab/actions-permissions/monitor@v1
14 | # with:
15 | # config: ${{ vars.PERMISSIONS_CONFIG }}
16 |
17 | - name: Setup .NET
18 | uses: actions/setup-dotnet@v4
19 | with:
20 | dotnet-version: |
21 | 8.0.x
22 |
23 | - name: Download Assets
24 | uses: i3h/download-release-asset@v1.3.3
25 | with:
26 | owner: ${{ github.event.repository.owner.login }}
27 | repo: ${{ github.event.repository.name }}
28 | tag: ${{ github.event.release.tag_name }}
29 | file: '/.*\.nupkg/'
30 | token: ${{ secrets.GITHUB_TOKEN }}
31 |
32 | - run: ls -alR
33 | name: List files
34 |
35 | - name: Publish the package to nuget.org
36 | run: dotnet nuget push "*.nupkg" --source https://api.nuget.org/v3/index.json -k $NUGET_AUTH_TOKEN --skip-duplicate
37 | env:
38 | NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | #packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
157 | /Libs
158 | /NuGet/tools/lib
159 | /NuGet/*.nupkg
160 | /.vs/
161 | /*.nupkg
162 |
--------------------------------------------------------------------------------
/Create-Package.ps1:
--------------------------------------------------------------------------------
1 | msbuild /p:Configuration=Release
2 |
3 | Write-Host "Expect 1 warning"
4 | .\nuget.exe pack .\PowerShellWixExtension.nuspec -OutputDirectory .\NuGet
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 3.3.37
6 | all
7 |
8 |
9 |
--------------------------------------------------------------------------------
/GitVersion.yml:
--------------------------------------------------------------------------------
1 | assembly-versioning-scheme: MajorMinorPatchTag
2 | mode: ContinuousDelivery
3 | branches: {}
4 | ignore:
5 | sha: []
6 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2014 David Gardiner
2 |
3 | Some files (where indicated) are licensed under the Microsoft Reciprocal License
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
--------------------------------------------------------------------------------
/MSRL-LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2004, Outercurve Foundation.
2 | This software is released under the Microsoft Reciprocal License (MS-RL) (the "License"); you may not use the software except in compliance with the License.
3 |
4 | The text of the Microsoft Reciprocal License (MS-RL) can be found online at:
5 | http://opensource.org/licenses/ms-rl
6 |
7 |
8 | Microsoft Reciprocal License (MS-RL)
9 |
10 | This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
11 |
12 | 1. Definitions
13 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
14 | A "contribution" is the original software, or any additions or changes to the software.
15 | A "contributor" is any person that distributes its contribution under this license.
16 | "Licensed patents" are a contributor's patent claims that read directly on its contribution.
17 |
18 | 2. Grant of Rights
19 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
20 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
21 |
22 | 3. Conditions and Limitations
23 | (A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.
24 | (B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
25 | (C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
26 | (D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
27 | (E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
28 | (F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
29 |
--------------------------------------------------------------------------------
/NuGet/content/PowerShellWixExtension.DummyFile.txt:
--------------------------------------------------------------------------------
1 | This file is used to invoke the PowerShell scripts during NuGet package installation.
2 | It should be removed automatically after the package is installed. If this file is still present in your project, you can safely delete it.
--------------------------------------------------------------------------------
/NuGet/tools/Install.ps1:
--------------------------------------------------------------------------------
1 | # Created by Alexander Köplinger, 2013
2 |
3 | param($installPath, $toolsPath, $package, $project)
4 |
5 | # ensure that we are installing into a WiX project
6 | if ($project.Kind -ne '{930c7802-8a8c-48f9-8165-68863bccd9dd}')
7 | {
8 | throw "'$($project.Name)' is not a WiX project! This package will only work on WiX projects."
9 | }
10 |
11 | # remove dummy file from project
12 | $dummy = $project.ProjectItems.Item("PowerShellWixExtension.DummyFile.txt").Delete()
13 |
14 | $msBuildProj = @([Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName))[0]
15 |
16 | # remove previous changes (for cases where Uninstall.ps1 wasn't executed properly)
17 | Import-Module (Join-Path $toolsPath "Remove.psm1")
18 | Remove-Changes $msBuildProj
19 |
20 | # add the property group directly before the WixTargetsPath-Import, according to http://wixtoolset.org/documentation/manual/v3/msbuild/daily_builds.html
21 | $itemGroup = $msBuildProj.Xml.CreateItemGroupElement()
22 |
23 | $wixImport = $msBuildProj.Xml.Children | Where-Object { $_.Project -eq '$(WixTargetsPath)' }
24 | $msBuildProj.Xml.InsertBeforeChild($itemGroup, $wixImport)
25 |
26 | # Calculate relative path to package from project
27 | $projectDir = [System.IO.Path]::GetDirectoryName($project.FullName)
28 |
29 | Push-Location $projectDir
30 |
31 | $hintPath = Resolve-Path ($toolsPath + '\lib\PowerShellWixExtension.dll') -Relative
32 |
33 | Pop-Location
34 |
35 | #
36 | # ..\..\Libs\PowerShellWixExtension\PowerShellWixExtension.dll
37 | # PowerShellWixExtension
38 | #
39 |
40 | $metadata = New-Object 'System.Collections.Generic.Dictionary[String, String]'
41 | $metadata.Add("HintPath", $hintPath)
42 | $metadata.Add("Name", "PowerShellWixExtension")
43 | $itemGroup.AddItem('WixExtension', 'PowerShellWixExtension', $metadata)
44 |
45 | # save changes
46 | $project.Save($null)
47 | $msBuildProj.ReevaluateIfNecessary()
--------------------------------------------------------------------------------
/NuGet/tools/Remove.psm1:
--------------------------------------------------------------------------------
1 | # Created by Alexander Köplinger, 2013
2 |
3 | function Remove-Changes
4 | {
5 | param(
6 | [parameter(Position = 0, Mandatory = $true)]
7 | [Microsoft.Build.Evaluation.Project]$msBuildProj
8 | )
9 |
10 | #TODO: this can probably be improved
11 | $wixToolPathProperties = $msBuildProj.Xml.AllChildren | Where-Object { $_.Include -eq 'PowerShellWixExtension' }
12 |
13 | if ($wixToolPathProperties)
14 | {
15 | foreach($item in $wixToolPathProperties)
16 | {
17 | $itemGroup = $item.Parent
18 | $itemGroup.RemoveChild($item)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/NuGet/tools/Uninstall.ps1:
--------------------------------------------------------------------------------
1 | # Originally created by Alexander Köplinger, 2013
2 |
3 | param($installPath, $toolsPath, $package, $project)
4 |
5 | $msBuildProj = @([Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName))[0]
6 |
7 | # remove changes
8 | Import-Module (Join-Path $toolsPath "Remove.psm1")
9 | Remove-Changes $msBuildProj
10 |
11 | # need to add and remove a dummy item, otherwise saving the project doesn't work.
12 | $project.ProjectItems.AddFolder("PowerShellWixExtension.DummyFolder", $null).Delete()
13 |
14 | # save changes
15 | $project.Save($null)
16 | $msBuildProj.ReevaluateIfNecessary()
--------------------------------------------------------------------------------
/PowerShellActions/CustomAction.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/PowerShellActions/CustomAction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Xml.Linq;
4 | using System.Xml.Serialization;
5 | using Microsoft.Deployment.WindowsInstaller;
6 |
7 | using View = Microsoft.Deployment.WindowsInstaller.View;
8 | using System.Collections.Generic;
9 | using System.IO;
10 |
11 | namespace PowerShellActions
12 | {
13 | public class CustomActions
14 | {
15 | public const uint TickIncrement = 10000;
16 |
17 | // Specify or calculate the total number of ticks the custom action adds to the length of the ProgressBar
18 | public const uint TotalTicks = TickIncrement * NumberItems;
19 | private const uint NumberItems = 100;
20 |
21 | private const string PowerShellFilesElevatedDeferredProperty = "PowerShellFilesElevatedDeferred";
22 | private const string PowerShellFilesDeferredProperty = "PowerShellFilesDeferred";
23 | private const string PowerShellScriptsElevatedDeferredProperty = "PowerShellScriptsElevatedDeferred";
24 | private const string PowerShellScriptsDeferredProperty = "PowerShellScriptsDeferred";
25 |
26 | private const string PowerShellFilesElevatedUninstallDeferredProperty = "PowerShellFilesElevatedUninstallDeferred";
27 | private const string PowerShellFilesUninstallDeferredProperty = "PowerShellFilesUninstallDeferred";
28 | private const string PowerShellScriptsElevatedUninstallDeferredProperty = "PowerShellScriptsElevatedUninstallDeferred";
29 | private const string PowerShellScriptsUninstallDeferredProperty = "PowerShellScriptsUninstallDeferred";
30 |
31 | [CustomAction]
32 | public static ActionResult PowerShellFilesImmediate(Session session)
33 | {
34 | session.Log("PowerShellFilesImmediate start");
35 |
36 | return FilesImmediate(session, 0, PowerShellFilesDeferredProperty);
37 | }
38 |
39 | [CustomAction]
40 | public static ActionResult PowerShellFilesDeferred(Session session)
41 | {
42 | session.Log("PowerShellFilesDeferred start");
43 |
44 | return FilesDeferred(session, PowerShellFilesDeferredProperty);
45 | }
46 |
47 | [CustomAction]
48 | public static ActionResult PowerShellFilesElevatedImmediate(Session session)
49 | {
50 | session.Log("PowerShellFilesElevatedImmediate start");
51 |
52 | return FilesImmediate(session, 1, PowerShellFilesElevatedDeferredProperty);
53 | }
54 |
55 | [CustomAction]
56 | public static ActionResult PowerShellFilesElevatedDeferred(Session session)
57 | {
58 | session.Log("PowerShellFilesElevatedDeferred start");
59 |
60 | return FilesDeferred(session, PowerShellFilesElevatedDeferredProperty);
61 | }
62 |
63 | [CustomAction]
64 | public static ActionResult PowerShellFilesUninstall(Session session)
65 | {
66 | session.Log("PowerShellFilesUninstall start");
67 |
68 | return FilesImmediate(session, 0, PowerShellFilesUninstallDeferredProperty);
69 | }
70 |
71 |
72 | [CustomAction]
73 | public static ActionResult PowerShellFilesUninstallDeferred(Session session)
74 | {
75 | session.Log("PowerShellFilesUninstallDeferred start");
76 |
77 | return FilesDeferred(session, PowerShellFilesUninstallDeferredProperty);
78 | }
79 |
80 |
81 | [CustomAction]
82 | public static ActionResult PowerShellFilesElevatedUninstall(Session session)
83 | {
84 | session.Log("PowerShellFilesElevatedUninstall start");
85 |
86 | return FilesImmediate(session, 1, PowerShellFilesElevatedUninstallDeferredProperty);
87 | }
88 |
89 | [CustomAction]
90 | public static ActionResult PowerShellFilesElevatedUninstallDeferred(Session session)
91 | {
92 | session.Log("PowerShellFilesElevatedUninstallDeferred start");
93 |
94 | return FilesDeferred(session, PowerShellFilesElevatedUninstallDeferredProperty);
95 | }
96 |
97 | [CustomAction]
98 | public static ActionResult PowerShellScriptsImmediate(Session session)
99 | {
100 | session.Log("PowerShellScriptsImmediate start");
101 |
102 | return ScriptsImmediate(session, 0, PowerShellScriptsDeferredProperty);
103 | }
104 |
105 | [CustomAction]
106 | public static ActionResult PowerShellScriptsDeferred(Session session)
107 | {
108 | session.Log("PowerShellScriptsDeferred start");
109 |
110 | return ScriptsDeferred(session, PowerShellScriptsDeferredProperty);
111 | }
112 |
113 | [CustomAction]
114 | public static ActionResult PowerShellScriptsElevatedImmediate(Session session)
115 | {
116 | session.Log("PowerShellScriptsElevatedImmediate start");
117 |
118 | return ScriptsImmediate(session, 1, PowerShellScriptsElevatedDeferredProperty);
119 | }
120 |
121 | [CustomAction]
122 | public static ActionResult PowerShellScriptsElevatedDeferred(Session session)
123 | {
124 | session.Log("PowerShellScriptsElevatedDeferred start");
125 |
126 | return ScriptsDeferred(session, PowerShellScriptsElevatedDeferredProperty);
127 | }
128 |
129 | [CustomAction]
130 | public static ActionResult PowerShellScriptsUninstall(Session session)
131 | {
132 | session.Log("PowerShellScriptsUninstall start");
133 |
134 | return ScriptsImmediate(session, 0, PowerShellScriptsUninstallDeferredProperty);
135 | }
136 |
137 | [CustomAction]
138 | public static ActionResult PowerShellScriptsUninstallDeferred(Session session)
139 | {
140 | session.Log("PowerShellScriptsUninstallDeferred start");
141 |
142 | return ScriptsDeferred(session, PowerShellScriptsUninstallDeferredProperty);
143 | }
144 |
145 | [CustomAction]
146 | public static ActionResult PowerShellScriptsElevatedUninstall(Session session)
147 | {
148 | session.Log("PowerShellScriptsElevatedUninstall start");
149 |
150 | return ScriptsImmediate(session, 1, PowerShellScriptsElevatedUninstallDeferredProperty);
151 | }
152 |
153 | [CustomAction]
154 | public static ActionResult PowerShellScriptsElevatedUninstallDeferred(Session session)
155 | {
156 | session.Log("PowerShellScriptsElevatedUninstallDeferred start");
157 |
158 | return ScriptsDeferred(session, PowerShellScriptsElevatedUninstallDeferredProperty);
159 | }
160 |
161 | [Serializable]
162 | public class ScriptActionData
163 | {
164 | public string Id { get; set; }
165 | public string Script { get; set; }
166 | public bool IgnoreErrors { get; set; }
167 | }
168 |
169 | private static ActionResult ScriptsImmediate(Session session, int elevated, string deferredProperty)
170 | {
171 | Database db = session.Database;
172 |
173 | if (!db.Tables.Contains("PowerShellScripts"))
174 | return ActionResult.Success;
175 |
176 | try
177 | {
178 | List scripts = new List();
179 | using (View view = db.OpenView(string.Format("SELECT `Id`, `Script`, `IgnoreErrors`, `Condition` FROM `PowerShellScripts` WHERE `Elevated` = {0} ORDER BY `Order`", elevated)))
180 | {
181 | view.Execute();
182 |
183 | Record row;
184 | while ((row = view.Fetch()) != null)
185 | {
186 | string condition = row["Condition"]?.ToString();
187 | if (!string.IsNullOrEmpty(condition) && !session.EvaluateCondition(condition))
188 | {
189 | session.Log($"Condition evaluated to false. Skip PS script {row["Id"]?.ToString()}");
190 | continue;
191 | }
192 |
193 | string script = Encoding.Unicode.GetString(Convert.FromBase64String(row["Script"].ToString()));
194 | script = session.Format(script);
195 | script = Convert.ToBase64String(Encoding.Unicode.GetBytes(script));
196 |
197 | ScriptActionData data = new ScriptActionData()
198 | {
199 | Id = row["Id"].ToString(),
200 | Script = script,
201 | IgnoreErrors = row["IgnoreErrors"].ToString() == "1"
202 | };
203 |
204 | scripts.Add(data);
205 | session.Log("Adding {0} to CustomActionData", data.Id);
206 | }
207 | }
208 |
209 | XmlSerializer srlz = new XmlSerializer(scripts.GetType());
210 | using (StringWriter sw = new StringWriter())
211 | {
212 | srlz.Serialize(sw, scripts);
213 | session[deferredProperty] = sw.ToString();
214 | }
215 |
216 | // Tell the installer to increase the value of the final total
217 | // length of the progress bar by the total number of ticks in
218 | // the custom action.
219 | MessageResult iResult;
220 | using (var hProgressRec = new Record(2))
221 | {
222 | hProgressRec[1] = 3;
223 | hProgressRec[2] = TotalTicks;
224 | iResult = session.Message(InstallMessage.Progress, hProgressRec);
225 | }
226 |
227 | if (iResult == MessageResult.Cancel)
228 | {
229 | return ActionResult.UserExit;
230 | }
231 |
232 | return ActionResult.Success;
233 | }
234 | catch (Exception ex)
235 | {
236 | session.Log(ex.ToString());
237 | return ActionResult.Failure;
238 | }
239 | finally
240 | {
241 | db.Close();
242 | }
243 | }
244 |
245 | private static ActionResult ScriptsDeferred(Session session, string deferredProperty)
246 | {
247 | MessageResult iResult;
248 | using (var hActionRec = new Record(3))
249 | {
250 | hActionRec[1] = deferredProperty;
251 | hActionRec[2] = "PowerShell Scripts";
252 | hActionRec[3] = "[1] of [2], [3]";
253 | iResult = session.Message(InstallMessage.ActionStart, hActionRec);
254 | }
255 |
256 | if (iResult == MessageResult.Cancel)
257 | {
258 | return ActionResult.UserExit;
259 | }
260 |
261 | // Tell the installer to use explicit progress messages.
262 | using (var hProgressRec = new Record(3))
263 | {
264 | hProgressRec[1] = 1;
265 | hProgressRec[2] = 1;
266 | hProgressRec[3] = 0;
267 | iResult = session.Message(InstallMessage.Progress, hProgressRec);
268 | }
269 |
270 | if (iResult == MessageResult.Cancel)
271 | {
272 | return ActionResult.UserExit;
273 | }
274 |
275 | try
276 | {
277 | List scripts = new List();
278 | string cad = session["CustomActionData"];
279 | XmlSerializer srlz = new XmlSerializer(scripts.GetType());
280 | if (string.IsNullOrWhiteSpace(cad))
281 | {
282 | session.Log("Nothing to do");
283 | return ActionResult.Success;
284 | }
285 |
286 | using (StringReader sr = new StringReader(cad))
287 | {
288 | IEnumerable tempScripts = srlz.Deserialize(sr) as IEnumerable;
289 | if (tempScripts != null)
290 | {
291 | scripts.AddRange(tempScripts);
292 | }
293 | }
294 |
295 | foreach (ScriptActionData datum in scripts)
296 | {
297 | string script = Encoding.Unicode.GetString(Convert.FromBase64String(datum.Script));
298 | session.Log($"Executing PowerShell script {datum.Id}:\n{script}");
299 |
300 | using (var task = new PowerShellTask(script, session))
301 | {
302 | bool result = false;
303 | try
304 | {
305 | result = task.Execute();
306 | session.Log("PowerShell terminating errors: {0}", result);
307 | }
308 | catch (Exception ex)
309 | {
310 | result = false;
311 | session.Log(ex.ToString());
312 | }
313 | if (!result)
314 | {
315 | if (datum.IgnoreErrors)
316 | {
317 | session.Log("Script execution failed. Ignoring error");
318 | continue;
319 | }
320 |
321 | session.Log("Returning Failure");
322 | return ActionResult.Failure;
323 | }
324 | }
325 | }
326 |
327 | return ActionResult.Success;
328 | }
329 | catch (Exception ex)
330 | {
331 | session.Log("PowerShell terminating error, returning Failure");
332 | session.Log(ex.ToString());
333 | return ActionResult.Failure;
334 | }
335 | }
336 |
337 | private static ActionResult FilesImmediate(Session session, int elevated, string deferredProperty)
338 | {
339 | Database db = session.Database;
340 |
341 | const string tableName = "PowerShellFiles";
342 | if (!db.Tables.Contains(tableName))
343 | return ActionResult.Success;
344 |
345 | try
346 | {
347 | XDocument doc;
348 | using (View view = db.OpenView(string.Format("SELECT `Id`, `File`, `Arguments`, `IgnoreErrors`, `Condition` FROM `{0}` WHERE `Elevated` = {1} ORDER BY `Order`", tableName, elevated)))
349 | {
350 | view.Execute();
351 |
352 | doc = new XDocument(new XDeclaration("1.0", "utf-16", "yes"), new XElement("r"));
353 |
354 | foreach (Record row in view)
355 | {
356 | string condition = row["Condition"]?.ToString();
357 | if (!string.IsNullOrEmpty(condition) && !session.EvaluateCondition(condition))
358 | {
359 | session.Log($"Condition evaluated to false. Skip PS file {row["Id"]?.ToString()}");
360 | continue;
361 | }
362 |
363 | var args = session.Format(row["Arguments"].ToString());
364 | var IgnoreErrors = session.Format(row["IgnoreErrors"].ToString());
365 |
366 | session.Log("args '{0}'", args);
367 |
368 | doc.Root.Add(new XElement("d", new XAttribute("Id", row["Id"]),
369 | new XAttribute("file", session.Format(row["File"].ToString())), new XAttribute("args", args), new XAttribute("IgnoreErrors", IgnoreErrors)));
370 | }
371 | }
372 |
373 | var cad = new CustomActionData { { "xml", doc.ToString() } };
374 |
375 | session[deferredProperty] = cad.ToString();
376 |
377 | // Tell the installer to increase the value of the final total
378 | // length of the progress bar by the total number of ticks in
379 | // the custom action.
380 | MessageResult iResult;
381 | using (var hProgressRec = new Record(2))
382 | {
383 | hProgressRec[1] = 3;
384 | hProgressRec[2] = TotalTicks;
385 | iResult = session.Message(InstallMessage.Progress, hProgressRec);
386 | }
387 |
388 | if (iResult == MessageResult.Cancel)
389 | {
390 | return ActionResult.UserExit;
391 | }
392 |
393 | return ActionResult.Success;
394 | }
395 | catch (Exception ex)
396 | {
397 | session.Log(ex.Message);
398 | return ActionResult.Failure;
399 | }
400 | finally
401 | {
402 | db.Close();
403 | }
404 | }
405 |
406 | private static ActionResult FilesDeferred(Session session, string deferredProperty)
407 | {
408 |
409 | // Installer is executing the installation script. Set up a
410 | // record specifying appropriate templates and text for
411 | // messages that will inform the user about what the custom
412 | // action is doing. Tell the installer to use this template and
413 | // text in progress messages.
414 | MessageResult iResult;
415 | using (var hActionRec = new Record(3))
416 | {
417 | hActionRec[1] = deferredProperty;
418 | hActionRec[2] = "PowerShell Files";
419 | hActionRec[3] = "[1] of [2], [3]";
420 | iResult = session.Message(InstallMessage.ActionStart, hActionRec);
421 | }
422 |
423 | if (iResult == MessageResult.Cancel)
424 | {
425 | return ActionResult.UserExit;
426 | }
427 |
428 | // Tell the installer to use explicit progress messages.
429 | using (var hProgressRec = new Record(3))
430 | {
431 | hProgressRec[1] = 1;
432 | hProgressRec[2] = 1;
433 | hProgressRec[3] = 0;
434 | iResult = session.Message(InstallMessage.Progress, hProgressRec);
435 | }
436 |
437 | if (iResult == MessageResult.Cancel)
438 | {
439 | return ActionResult.UserExit;
440 | }
441 |
442 | try
443 | {
444 | if (!session.CustomActionData.ContainsKey("xml"))
445 | {
446 | session.Log("Skipping as no CustomActionData key 'xml'");
447 | return ActionResult.NotExecuted;
448 | }
449 |
450 | string content = session.CustomActionData["xml"];
451 |
452 | XDocument doc = XDocument.Parse(content);
453 |
454 | foreach (XElement row in doc.Root.Elements("d"))
455 | {
456 | string file = row.Attribute("file").Value;
457 | string arguments = row.Attribute("args").Value;
458 | string IgnoreErrors = row.Attribute("IgnoreErrors").Value;
459 | session.Log($"Executing PowerShell file: '{file}' {arguments}");
460 |
461 | using (var task = new PowerShellTask(file, arguments, session))
462 | {
463 | try
464 | {
465 | bool result = task.Execute();
466 | session.Log("PowerShell non-terminating errors: {0}", !result);
467 | if (!result)
468 | {
469 | if (!IgnoreErrors.Equals("0"))
470 | {
471 | session.Log("Ignoring failure due to 'IgnoreErrors' marking");
472 | }
473 | else
474 | {
475 | session.Log("Returning Failure");
476 | return ActionResult.Failure;
477 | }
478 | }
479 | }
480 | catch (Exception ex)
481 | {
482 | if (!IgnoreErrors.Equals("0"))
483 | {
484 | session.Log("Ignoring PowerShell error due to 'IgnoreErrors' marking");
485 | session.Log(ex.ToString());
486 | }
487 | else
488 | {
489 | session.Log("PowerShell terminating error, returning Failure");
490 | session.Log(ex.ToString());
491 | return ActionResult.Failure;
492 | }
493 | }
494 | }
495 | }
496 |
497 | return ActionResult.Success;
498 | }
499 | catch (Exception ex)
500 | {
501 | session.Log("PowerShell terminating error, returning Failure");
502 | session.Log(ex.ToString());
503 | return ActionResult.Failure;
504 | }
505 | }
506 | }
507 | }
--------------------------------------------------------------------------------
/PowerShellActions/IExitCode.cs:
--------------------------------------------------------------------------------
1 | namespace PowerShellActions
2 | {
3 | internal interface IExitCode
4 | {
5 | int ExitCode { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/PowerShellActions/PowerShellActions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}
9 | Library
10 | Properties
11 | PowerShellActions
12 | PowerShellActions
13 | v4.5
14 | 512
15 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.CA.targets
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 | False
39 | ..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/PowerShellActions/PowerShellTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Linq;
4 | using System.Management.Automation;
5 | using System.Management.Automation.Runspaces;
6 | using System.Text;
7 | using Microsoft.Deployment.WindowsInstaller;
8 |
9 | namespace PowerShellActions
10 | {
11 | internal class PowerShellTask : IDisposable, IExitCode
12 | {
13 | private readonly Session _session;
14 |
15 | ///
16 | /// The context that the Windows PowerShell script will run under.
17 | ///
18 | private Pipeline _pipeline;
19 |
20 | internal PowerShellTask(string script, Session session)
21 | {
22 | _session = session;
23 | Runspace runspace = RunspaceFactory.CreateRunspace(new WixHost(session, this));
24 |
25 | _pipeline = runspace.CreatePipeline();
26 | _pipeline.Commands.AddScript(script);
27 | _pipeline.Runspace.Open();
28 | _pipeline.Runspace.SessionStateProxy.SetVariable("session", session);
29 | }
30 |
31 | internal PowerShellTask(string file, string arguments, Session session)
32 | {
33 | _session = session;
34 | RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
35 | Runspace runspace = RunspaceFactory.CreateRunspace(new WixHost(session, this), runspaceConfiguration);
36 |
37 | runspace.Open();
38 |
39 | var scriptInvoker = new RunspaceInvoke(runspace);
40 | scriptInvoker.Invoke("Set-ExecutionPolicy RemoteSigned -Scope Process");
41 |
42 | _pipeline = runspace.CreatePipeline();
43 |
44 | // http://stackoverflow.com/a/530418/25702
45 | _pipeline.Commands.AddScript(string.Format("& '{0}' {1}", file, arguments));
46 | _pipeline.Runspace.SessionStateProxy.SetVariable("session", session);
47 | }
48 |
49 | public int ExitCode { get; set; }
50 |
51 | public void Dispose()
52 | {
53 | Dispose(true);
54 | GC.SuppressFinalize(this);
55 | }
56 |
57 | ///
58 | /// Execute Script, return false if any errors
59 | ///
60 | ///
61 | public bool Execute()
62 | {
63 | var results = _pipeline.Invoke();
64 |
65 | using (var record = new Record(0))
66 | {
67 | record[0] = string.Format("Exit code {0}", ExitCode);
68 | _session.Message(InstallMessage.Info, record);
69 |
70 | if (results?.Any() ?? false)
71 | {
72 | _session.Log("Output");
73 |
74 | foreach (var r in results)
75 | {
76 | if (r?.BaseObject != null)
77 | {
78 | _session.Log("\t" + r?.BaseObject?.ToString() ?? "");
79 | }
80 | }
81 | }
82 |
83 | var errors = Errors();
84 | if (errors != null)
85 | {
86 | _session.Log("Non-terminating errors");
87 |
88 | record[0] = errors;
89 | _session.Message(InstallMessage.Error, record);
90 | }
91 |
92 | // Using .Error instead of .HadErrors to support any PS version.
93 | return (((_pipeline?.Error?.Count ?? 0) == 0) && (errors == null) && (ExitCode == 0));
94 | }
95 | }
96 |
97 | public string Errors()
98 | {
99 | // check for errors (non-terminating)
100 | if ((_pipeline?.Error?.Count ?? 0) > 0)
101 | {
102 | var builder = new StringBuilder();
103 |
104 | // iterate over Error PipeLine until end
105 | while (!_pipeline.Error.EndOfPipeline)
106 | {
107 | // read one PSObject off the pipeline
108 | var value = _pipeline.Error.Read() as PSObject;
109 | if (value != null)
110 | {
111 | // get the ErrorRecord
112 | var r = value.BaseObject as ErrorRecord;
113 | if (r != null)
114 | {
115 | // build whatever kind of message you want
116 | builder.AppendLine(r.InvocationInfo?.MyCommand?.Name ?? "" + " : " + r.Exception.Message);
117 | builder.AppendLine(r.InvocationInfo?.PositionMessage ?? "");
118 | builder.AppendLine(string.Format("+ CategoryInfo: {0}", r.CategoryInfo));
119 | builder.AppendLine(
120 | string.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId ?? ""));
121 | }
122 | }
123 | }
124 | return builder.ToString();
125 | }
126 |
127 | return null;
128 | }
129 |
130 | protected virtual void Dispose(bool disposing)
131 | {
132 | if (disposing)
133 | {
134 | if (_pipeline.Runspace != null)
135 | {
136 | _pipeline.Runspace.Dispose();
137 | _pipeline = null;
138 | }
139 | }
140 | }
141 | }
142 | }
--------------------------------------------------------------------------------
/PowerShellActions/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("PowerShellActions")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("PowerShellActions")]
11 | [assembly: AssemblyCopyright("Copyright © David Gardiner 2014-2021")]
12 | [assembly: AssemblyTrademark("")]
13 | [assembly: AssemblyCulture("")]
14 |
15 | // Setting ComVisible to false makes the types in this assembly not visible
16 | // to COM components. If you need to access a type in this assembly from
17 | // COM, set the ComVisible attribute to true on that type.
18 | [assembly: ComVisible(false)]
19 |
20 | // The following GUID is for the ID of the typelib if this project is exposed to COM
21 | [assembly: Guid("e9c2a5aa-6c22-41f0-bf56-6a62b83d0001")]
22 |
--------------------------------------------------------------------------------
/PowerShellActions/WixHost.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Management.Automation.Host;
4 | using System.Threading;
5 |
6 | using Microsoft.Deployment.WindowsInstaller;
7 |
8 | namespace PowerShellActions
9 | {
10 | internal class WixHost : PSHost
11 | {
12 | private readonly IExitCode _exitCode;
13 | private readonly Guid _guid;
14 | private readonly PSHostUserInterface _wixHostUserInterface;
15 |
16 | public WixHost(Session session, IExitCode exitCode)
17 | {
18 | _exitCode = exitCode;
19 | _wixHostUserInterface = new WixHostUserInterface(session);
20 | _guid = Guid.NewGuid();
21 | }
22 |
23 | public override string Name
24 | {
25 | get
26 | {
27 | return "WixHost";
28 | }
29 | }
30 |
31 | public override PSHostUserInterface UI
32 | {
33 | get
34 | {
35 | return _wixHostUserInterface;
36 | }
37 | }
38 |
39 | public override CultureInfo CurrentCulture
40 | {
41 | get
42 | {
43 | return Thread.CurrentThread.CurrentCulture;
44 | }
45 | }
46 |
47 | public override CultureInfo CurrentUICulture
48 | {
49 | get
50 | {
51 | return Thread.CurrentThread.CurrentUICulture;
52 | }
53 | }
54 |
55 | public override Guid InstanceId
56 | {
57 | get
58 | {
59 | return _guid;
60 | }
61 | }
62 |
63 | public override Version Version
64 | {
65 | get
66 | {
67 | return new Version(1, 0, 0, 0);
68 | }
69 | }
70 |
71 | public override void EnterNestedPrompt()
72 | {
73 | throw new NotImplementedException("EnterNestedPrompt");
74 | }
75 |
76 | public override void ExitNestedPrompt()
77 | {
78 | throw new NotImplementedException("ExitNestedPrompt");
79 | }
80 |
81 | public override void NotifyBeginApplication()
82 | {
83 | }
84 |
85 | public override void NotifyEndApplication()
86 | {
87 | }
88 |
89 | public override void SetShouldExit(int exitCode)
90 | {
91 | _exitCode.ExitCode = exitCode;
92 | }
93 | }
94 | }
--------------------------------------------------------------------------------
/PowerShellActions/WixHostRawUserInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation.Host;
3 |
4 | namespace PowerShellActions
5 | {
6 | public class WixHostRawUserInterface : PSHostRawUserInterface
7 | {
8 | public WixHostRawUserInterface()
9 | {
10 | BufferSize = new Size(130, 25);
11 | }
12 |
13 | public override ConsoleColor BackgroundColor { get; set; }
14 | public override Size BufferSize { get; set; }
15 | public override Coordinates CursorPosition { get; set; }
16 | public override int CursorSize { get; set; }
17 | public override ConsoleColor ForegroundColor { get; set; }
18 |
19 | public override bool KeyAvailable
20 | {
21 | get
22 | {
23 | throw new NotImplementedException("KeyAvailable");
24 | }
25 | }
26 |
27 | public override Size MaxPhysicalWindowSize
28 | {
29 | get
30 | {
31 | throw new NotImplementedException("MaxPhysicalWindowSize");
32 | }
33 | }
34 |
35 | public override Size MaxWindowSize
36 | {
37 | get
38 | {
39 | throw new NotImplementedException("MaxWindowSize");
40 | }
41 | }
42 |
43 | public override Coordinates WindowPosition { get; set; }
44 | public override Size WindowSize { get; set; }
45 | public override string WindowTitle { get; set; }
46 |
47 | public override KeyInfo ReadKey(ReadKeyOptions options)
48 | {
49 | throw new NotImplementedException("ReadKey");
50 | }
51 |
52 | public override void FlushInputBuffer()
53 | {
54 | }
55 |
56 | public override void SetBufferContents(Coordinates origin, BufferCell[,] contents)
57 | {
58 | }
59 |
60 | public override void SetBufferContents(Rectangle rectangle, BufferCell fill)
61 | {
62 | }
63 |
64 | public override BufferCell[,] GetBufferContents(Rectangle rectangle)
65 | {
66 | throw new NotImplementedException("GetBufferContents");
67 | }
68 |
69 | public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill)
70 | {
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/PowerShellActions/WixHostUserInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Management.Automation;
6 | using System.Management.Automation.Host;
7 | using System.Security;
8 |
9 | using Microsoft.Deployment.WindowsInstaller;
10 |
11 | namespace PowerShellActions
12 | {
13 | internal class WixHostUserInterface : PSHostUserInterface
14 | {
15 | private readonly Session _session;
16 | private readonly WixHostRawUserInterface _wixHostRawUserInterface;
17 | private string _progressActivity;
18 |
19 | public WixHostUserInterface(Session session)
20 | {
21 | _session = session;
22 | _wixHostRawUserInterface = new WixHostRawUserInterface();
23 | _progressActivity = string.Empty;
24 | }
25 |
26 | [SuppressMessage("StyleCopPlus.StyleCopPlusRules", "SP0100:AdvancedNamingRules", Justification = "Reviewed. Suppression is OK here.")]
27 | public override PSHostRawUserInterface RawUI
28 | {
29 | get
30 | {
31 | return _wixHostRawUserInterface;
32 | }
33 | }
34 |
35 | public override int PromptForChoice(string caption, string message, Collection choices, int defaultChoice)
36 | {
37 | throw new NotImplementedException("PromptForChoice");
38 | }
39 |
40 | public override PSCredential PromptForCredential(string caption, string message, string userName, string targetName, PSCredentialTypes allowedCredentialTypes, PSCredentialUIOptions options)
41 | {
42 | throw new NotImplementedException("PromptForCredential");
43 | }
44 |
45 | public override PSCredential PromptForCredential(string caption, string message, string userName, string targetName)
46 | {
47 | throw new NotImplementedException("PromptForCredential");
48 | }
49 |
50 | public override string ReadLine()
51 | {
52 | throw new NotImplementedException("ReadLine");
53 | }
54 |
55 | public override SecureString ReadLineAsSecureString()
56 | {
57 | throw new NotImplementedException("ReadLineAsSecureString");
58 | }
59 |
60 | public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value)
61 | {
62 | _session.Log(value);
63 | }
64 |
65 | public override void Write(string value)
66 | {
67 | _session.Log(value);
68 | }
69 |
70 | public override void WriteDebugLine(string message)
71 | {
72 | _session.Log(message);
73 | }
74 |
75 | public override void WriteErrorLine(string value)
76 | {
77 | var record = new Record(0);
78 | record[0] = value;
79 | _session.Message(InstallMessage.Error, record);
80 | }
81 |
82 | public override void WriteLine(string value)
83 | {
84 | _session.Log(value);
85 | }
86 |
87 | public override void WriteProgress(long sourceId, ProgressRecord progressRecord)
88 | {
89 | Record hActionRec = new Record(3);
90 | Record hProgressRec = new Record(3);
91 |
92 | // Installer is executing the installation script. Set up a
93 | // record specifying appropriate templates and text for
94 | // messages that will inform the user about what the custom
95 | // action is doing. Tell the installer to use this template and
96 | // text in progress messages.
97 | hActionRec[1] = progressRecord.PercentComplete;
98 | hActionRec[2] = 100; // 100%
99 | hActionRec[3] = progressRecord.CurrentOperation;
100 |
101 | // Specify that an update of the progress bar’s position in
102 | // this case means to move it forward by one increment.
103 | hProgressRec[1] = 2;
104 | hProgressRec[2] = CustomActions.TickIncrement;
105 | hProgressRec[3] = 0;
106 |
107 | _session.Message(InstallMessage.ActionData, hActionRec);
108 | _session.Message(InstallMessage.Progress, hProgressRec);
109 | }
110 |
111 | public override void WriteVerboseLine(string message)
112 | {
113 | _session.Log(message);
114 | }
115 |
116 | public override void WriteWarningLine(string message)
117 | {
118 | var record = new Record(0);
119 | record[0] = message;
120 | _session.Message(InstallMessage.Warning, record);
121 | }
122 |
123 | public override Dictionary Prompt(string caption, string message, Collection descriptions)
124 | {
125 | throw new NotImplementedException("Prompt");
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/PowerShellLibrary/Library.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
18 |
19 |
24 |
25 |
31 |
32 |
37 |
38 |
44 |
45 |
50 |
51 |
57 |
58 |
63 |
64 |
70 |
71 |
76 |
77 |
83 |
84 |
89 |
90 |
96 |
97 |
102 |
103 |
109 |
110 |
111 |
112 | NOT Installed
113 |
114 | NOT Installed
115 |
116 | NOT Installed
117 |
118 | NOT Installed
119 |
120 |
121 | NOT Installed
122 |
123 | NOT Installed
124 |
125 | NOT Installed
126 |
127 | NOT Installed
128 |
129 |
130 | REMOVE="ALL"
131 |
132 | REMOVE="ALL"
133 |
134 | REMOVE="ALL"
135 |
136 | REMOVE="ALL"
137 |
138 |
139 | REMOVE="ALL"
140 |
141 | REMOVE="ALL"
142 |
143 | REMOVE="ALL"
144 |
145 | REMOVE="ALL"
146 |
147 |
148 |
149 | PowerShell Files
150 | PowerShell Inline
151 | PowerShell Inline (elevated)
152 | PowerShell Files (elevated)
153 |
154 | PowerShell Uninstall Files
155 | PowerShell Uninstall Inline
156 | PowerShell Uninstall Inline (elevated)
157 | PowerShell Uninstall Files (elevated)
158 |
159 |
160 |
--------------------------------------------------------------------------------
/PowerShellLibrary/PowerShellLibrary.wixproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 3.8
7 | 598472f5-d044-41f2-a8f0-82976139c499
8 | 2.0
9 | PowerShellLibrary
10 | Library
11 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
12 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
13 |
14 |
15 | bin\$(Configuration)\
16 | obj\$(Configuration)\
17 | Debug
18 | True
19 | False
20 | True
21 | True
22 |
23 |
24 | bin\$(Configuration)\
25 | obj\$(Configuration)\
26 | True
27 | False
28 | True
29 | True
30 |
31 |
32 |
33 |
34 |
35 |
36 | PowerShellActions
37 | {0a83f788-68c1-4533-8732-6b8e3fbc5282}
38 | True
39 | True
40 | Binaries;Content;Satellites
41 | INSTALLFOLDER
42 |
43 |
44 |
45 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/PowerShellWixExtension.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PowerShellWixExtension
5 | 2.1.0
6 | Wix Extension for PowerShell
7 | Wix Extension that allows running PowerShell scripts
8 | An extension for Wix that allows running PowerShell scripts, either from .ps1 files included in the MSI, or by embedding PowerShell script directly
9 | David Gardiner
10 | David Gardiner
11 | https://github.com/flcdrg/PowerShellWixExtension/
12 | LICENSE.txt
13 |
14 | false
15 | WiX PowerShell MSI Installer WixToolset XML
16 | $releasenotes$
17 | docs\README.md
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/PowerShellWixExtension.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25123.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerShellWixExtension", "PowerShellWixExtension\PowerShellWixExtension.csproj", "{C1A335B5-3575-4AEC-9260-8C18CE59DB9B}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {598472F5-D044-41F2-A8F0-82976139C499} = {598472F5-D044-41F2-A8F0-82976139C499}
9 | EndProjectSection
10 | EndProject
11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerShellActions", "PowerShellActions\PowerShellActions.csproj", "{0A83F788-68C1-4533-8732-6B8E3FBC5282}"
12 | EndProject
13 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerShellLibrary", "PowerShellLibrary\PowerShellLibrary.wixproj", "{598472F5-D044-41F2-A8F0-82976139C499}"
14 | EndProject
15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5A176C3F-31D2-43DB-BAEA-A0DF71CC34FF}"
16 | ProjectSection(SolutionItems) = preProject
17 | PowerShellWixExtension.nuspec = PowerShellWixExtension.nuspec
18 | tables.xsd = tables.xsd
19 | EndProjectSection
20 | EndProject
21 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D7480EA6-0D6B-4010-A15F-460EB85DF682}"
22 | EndProject
23 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerShellWixInlineScriptTest", "Tests\PowerShellWixInlineScriptTest\PowerShellWixInlineScriptTest.wixproj", "{BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}"
24 | EndProject
25 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerShellWixTest", "Tests\PowerShellWixTest\PowerShellWixTest.wixproj", "{0E852B37-0DD2-4FE9-8E20-123C0040F8BA}"
26 | EndProject
27 | Global
28 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
29 | Debug|Any CPU = Debug|Any CPU
30 | Debug|Mixed Platforms = Debug|Mixed Platforms
31 | Debug|x86 = Debug|x86
32 | Release|Any CPU = Release|Any CPU
33 | Release|Mixed Platforms = Release|Mixed Platforms
34 | Release|x86 = Release|x86
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
40 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
41 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Debug|x86.ActiveCfg = Debug|Any CPU
42 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
45 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
46 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}.Release|x86.ActiveCfg = Release|Any CPU
47 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Debug|Any CPU.ActiveCfg = Debug|x86
48 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
49 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Debug|Mixed Platforms.Build.0 = Debug|x86
50 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Debug|x86.ActiveCfg = Debug|x86
51 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Debug|x86.Build.0 = Debug|x86
52 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Release|Any CPU.ActiveCfg = Release|x86
53 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Release|Mixed Platforms.ActiveCfg = Release|x86
54 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Release|Mixed Platforms.Build.0 = Release|x86
55 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Release|x86.ActiveCfg = Release|x86
56 | {0A83F788-68C1-4533-8732-6B8E3FBC5282}.Release|x86.Build.0 = Release|x86
57 | {598472F5-D044-41F2-A8F0-82976139C499}.Debug|Any CPU.ActiveCfg = Debug|x86
58 | {598472F5-D044-41F2-A8F0-82976139C499}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
59 | {598472F5-D044-41F2-A8F0-82976139C499}.Debug|Mixed Platforms.Build.0 = Debug|x86
60 | {598472F5-D044-41F2-A8F0-82976139C499}.Debug|x86.ActiveCfg = Debug|x86
61 | {598472F5-D044-41F2-A8F0-82976139C499}.Debug|x86.Build.0 = Debug|x86
62 | {598472F5-D044-41F2-A8F0-82976139C499}.Release|Any CPU.ActiveCfg = Release|x86
63 | {598472F5-D044-41F2-A8F0-82976139C499}.Release|Mixed Platforms.ActiveCfg = Release|x86
64 | {598472F5-D044-41F2-A8F0-82976139C499}.Release|Mixed Platforms.Build.0 = Release|x86
65 | {598472F5-D044-41F2-A8F0-82976139C499}.Release|x86.ActiveCfg = Release|x86
66 | {598472F5-D044-41F2-A8F0-82976139C499}.Release|x86.Build.0 = Release|x86
67 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Debug|Any CPU.ActiveCfg = Debug|x86
68 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
69 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Debug|Mixed Platforms.Build.0 = Debug|x86
70 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Debug|x86.ActiveCfg = Debug|x86
71 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Debug|x86.Build.0 = Debug|x86
72 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Release|Any CPU.ActiveCfg = Release|x86
73 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Release|Mixed Platforms.ActiveCfg = Release|x86
74 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Release|Mixed Platforms.Build.0 = Release|x86
75 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Release|x86.ActiveCfg = Release|x86
76 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2}.Release|x86.Build.0 = Release|x86
77 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Debug|Any CPU.ActiveCfg = Debug|x86
78 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
79 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Debug|Mixed Platforms.Build.0 = Debug|x86
80 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Debug|x86.ActiveCfg = Debug|x86
81 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Debug|x86.Build.0 = Debug|x86
82 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Release|Any CPU.ActiveCfg = Release|x86
83 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Release|Mixed Platforms.ActiveCfg = Release|x86
84 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Release|Mixed Platforms.Build.0 = Release|x86
85 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Release|x86.ActiveCfg = Release|x86
86 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA}.Release|x86.Build.0 = Release|x86
87 | EndGlobalSection
88 | GlobalSection(SolutionProperties) = preSolution
89 | HideSolutionNode = FALSE
90 | EndGlobalSection
91 | GlobalSection(NestedProjects) = preSolution
92 | {BBA07F7F-E4D8-47F7-9A05-4CD6644236C2} = {D7480EA6-0D6B-4010-A15F-460EB85DF682}
93 | {0E852B37-0DD2-4FE9-8E20-123C0040F8BA} = {D7480EA6-0D6B-4010-A15F-460EB85DF682}
94 | EndGlobalSection
95 | EndGlobal
96 |
--------------------------------------------------------------------------------
/PowerShellWixExtension.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | 1
3 | False
4 | True
5 | True
6 | True
7 | True
8 | True
9 | True
--------------------------------------------------------------------------------
/PowerShellWixExtension/PowerShellCompilerExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Text;
4 | using System.Xml;
5 | using System.Xml.Schema;
6 | using Microsoft.Tools.WindowsInstallerXml;
7 |
8 | namespace PowerShellWixExtension
9 | {
10 | public class PowerShellCompilerExtension : CompilerExtension
11 | {
12 | private readonly XmlSchema _schema;
13 |
14 | public PowerShellCompilerExtension()
15 | {
16 | _schema = LoadXmlSchemaHelper(Assembly.GetExecutingAssembly(), "PowerShellWixExtension.PowerShellWixExtensionSchema.xsd");
17 | }
18 |
19 | public override XmlSchema Schema
20 | {
21 | get
22 | {
23 | return _schema;
24 | }
25 | }
26 |
27 | public override void ParseElement(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlElement element, params string[] contextValues)
28 | {
29 | switch (parentElement.LocalName)
30 | {
31 | case "Product":
32 | case "Fragment":
33 | switch (element.LocalName)
34 | {
35 | case "Script":
36 | ParseScriptElement(element);
37 | break;
38 | case "File":
39 | ParseFileElement(element);
40 | break;
41 | default:
42 | Core.UnexpectedElement(parentElement, element);
43 | break;
44 | }
45 |
46 | break;
47 | default:
48 | Core.UnexpectedElement(
49 | parentElement,
50 | element);
51 | break;
52 | }
53 | }
54 |
55 | private void ParseFileElement(XmlNode node)
56 | {
57 | SourceLineNumberCollection sourceLineNumber = Preprocessor.GetSourceLineNumbers(node);
58 |
59 | string superElementId = null;
60 | string file = null;
61 | string arguments = null;
62 | string condition = null;
63 | var elevated = YesNoType.No;
64 | YesNoType ignoreErrors = YesNoType.No;
65 | int order = 1000000000 + sourceLineNumber[0].LineNumber;
66 |
67 | foreach (XmlAttribute attribute in node.Attributes)
68 | {
69 | if (attribute.NamespaceURI.Length == 0 ||
70 | attribute.NamespaceURI == _schema.TargetNamespace)
71 | {
72 | switch (attribute.LocalName)
73 | {
74 | case "Id":
75 | superElementId = Core.GetAttributeIdentifierValue(sourceLineNumber, attribute);
76 | break;
77 | case "File":
78 | file = Core.GetAttributeValue(sourceLineNumber, attribute, false);
79 | break;
80 | case "Arguments":
81 | arguments = Core.GetAttributeValue(sourceLineNumber, attribute);
82 | break;
83 | case "Elevated":
84 | elevated = Core.GetAttributeYesNoValue(sourceLineNumber, attribute);
85 | break;
86 | case "IgnoreErrors":
87 | ignoreErrors = Core.GetAttributeYesNoValue(sourceLineNumber, attribute);
88 | break;
89 | case "Order":
90 | order = Core.GetAttributeIntegerValue(sourceLineNumber, attribute, 0, 1000000000);
91 | break;
92 | case "Condition":
93 | condition = Core.GetAttributeValue(sourceLineNumber, attribute);
94 | break;
95 | default:
96 | Core.UnexpectedAttribute(sourceLineNumber, attribute);
97 | break;
98 | }
99 | }
100 | else
101 | {
102 | Core.UnsupportedExtensionAttribute(sourceLineNumber, attribute);
103 | }
104 | }
105 |
106 | if (string.IsNullOrEmpty(superElementId))
107 | {
108 | Core.OnMessage(
109 | WixErrors.ExpectedAttribute(sourceLineNumber, node.Name, "Id"));
110 | }
111 |
112 | if (string.IsNullOrEmpty(file))
113 | {
114 | Core.OnMessage(
115 | WixErrors.ExpectedElement(sourceLineNumber, node.Name, "File"));
116 | }
117 |
118 | if (!Core.EncounteredError)
119 | {
120 | Row superElementRow = Core.CreateRow(sourceLineNumber, "PowerShellFiles");
121 |
122 | superElementRow[0] = superElementId;
123 | superElementRow[1] = file;
124 | superElementRow[2] = arguments;
125 | superElementRow[3] = elevated == YesNoType.Yes ? 1 : 0;
126 | superElementRow[4] = (ignoreErrors == YesNoType.Yes) ? 1 : 0;
127 | superElementRow[5] = order;
128 | superElementRow[6] = condition;
129 | }
130 |
131 | Core.CreateWixSimpleReferenceRow(sourceLineNumber, "CustomAction", "PowerShellFilesImmediate");
132 | }
133 |
134 | private void ParseScriptElement(XmlNode node)
135 | {
136 | SourceLineNumberCollection sourceLineNumber = Preprocessor.GetSourceLineNumbers(node);
137 |
138 | string superElementId = null;
139 | string scriptData = null;
140 | string condition = null;
141 | var elevated = YesNoType.No;
142 | YesNoType ignoreErrors = YesNoType.No;
143 | int order = 1000000000 + sourceLineNumber[0].LineNumber;
144 |
145 | foreach (XmlAttribute attribute in node.Attributes)
146 | {
147 | if (attribute.NamespaceURI.Length == 0 ||
148 | attribute.NamespaceURI == _schema.TargetNamespace)
149 | {
150 | switch (attribute.LocalName)
151 | {
152 | case "Id":
153 | superElementId = Core.GetAttributeIdentifierValue(sourceLineNumber, attribute);
154 | break;
155 | case "Elevated":
156 | elevated = Core.GetAttributeYesNoValue(sourceLineNumber, attribute);
157 | break;
158 | case "IgnoreErrors":
159 | ignoreErrors = Core.GetAttributeYesNoValue(sourceLineNumber, attribute);
160 | break;
161 | case "Order":
162 | order = Core.GetAttributeIntegerValue(sourceLineNumber, attribute, 0, 1000000000);
163 | break;
164 | case "Condition":
165 | condition = Core.GetAttributeValue(sourceLineNumber, attribute);
166 | break;
167 |
168 | default:
169 | Core.UnexpectedAttribute(sourceLineNumber, attribute);
170 | break;
171 | }
172 | }
173 | else
174 | {
175 | Core.UnsupportedExtensionAttribute(sourceLineNumber, attribute);
176 | }
177 | }
178 |
179 | if (node.HasChildNodes)
180 | {
181 | var cdata = node.ChildNodes[0] as XmlCDataSection;
182 |
183 | if (cdata != null)
184 |
185 | // Need to encode, as column doesn't like having line feeds
186 | scriptData = Convert.ToBase64String(Encoding.Unicode.GetBytes(cdata.Data));
187 | }
188 |
189 | if (string.IsNullOrEmpty(superElementId))
190 | {
191 | Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumber, node.Name, "Id"));
192 | }
193 |
194 | if (string.IsNullOrEmpty(scriptData))
195 | {
196 | Core.OnMessage(WixErrors.ExpectedElement(sourceLineNumber, node.Name, "CDATA"));
197 | }
198 |
199 | if (!Core.EncounteredError)
200 | {
201 | Row superElementRow = Core.CreateRow(sourceLineNumber, "PowerShellScripts");
202 |
203 | superElementRow[0] = superElementId;
204 | superElementRow[1] = scriptData;
205 | superElementRow[2] = elevated == YesNoType.Yes ? 1 : 0;
206 | superElementRow[3] = (ignoreErrors == YesNoType.Yes) ? 1 : 0;
207 | superElementRow[4] = order;
208 | superElementRow[5] = condition;
209 | }
210 |
211 | Core.CreateWixSimpleReferenceRow(sourceLineNumber, "CustomAction", "PowerShellScriptsImmediate");
212 | }
213 | }
214 | }
--------------------------------------------------------------------------------
/PowerShellWixExtension/PowerShellWixExtension.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using Microsoft.Tools.WindowsInstallerXml;
3 |
4 | namespace PowerShellWixExtension
5 | {
6 | public class PowerShellWixExtension : WixExtension
7 | {
8 | private CompilerExtension _compilerExtension;
9 | private Library _library;
10 | private TableDefinitionCollection _tableDefinitions;
11 |
12 | public override CompilerExtension CompilerExtension
13 | {
14 | get
15 | {
16 | return _compilerExtension ?? (_compilerExtension = new PowerShellCompilerExtension());
17 | }
18 | }
19 |
20 | public override TableDefinitionCollection TableDefinitions
21 | {
22 | get
23 | {
24 | return _tableDefinitions ?? (_tableDefinitions = LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "PowerShellWixExtension.TableDefinitions.xml"));
25 | }
26 | }
27 |
28 | public override Library GetLibrary(TableDefinitionCollection tableDefinitions)
29 | {
30 | return _library ?? (_library = LoadLibraryHelper(Assembly.GetExecutingAssembly(), "PowerShellWixExtension.PowerShellLibrary.wixlib", tableDefinitions));
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/PowerShellWixExtension/PowerShellWixExtension.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C1A335B5-3575-4AEC-9260-8C18CE59DB9B}
8 | Library
9 | Properties
10 | PowerShellWixExtension
11 | PowerShellWixExtension
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | PowerShellLibrary
47 | false
48 |
49 |
50 | $(WIX)\bin\wix.dll
51 |
52 |
53 |
54 |
55 |
56 |
57 | PowerShellWixExtensionSchema.xsd
58 |
59 |
60 |
61 |
62 |
63 | Designer
64 |
65 |
66 |
67 |
68 | Designer
69 |
70 |
71 |
72 |
73 | PowerShellLibrary.wixlib
74 |
75 |
76 |
77 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/PowerShellWixExtension/PowerShellWixExtensionSchema.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.Tools.WindowsInstallerXml;
8 |
9 | namespace PowerShellWixExtension
10 | {
11 | }
12 |
--------------------------------------------------------------------------------
/PowerShellWixExtension/PowerShellWixExtensionSchema.xsd:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 | The schema for the PowerShellWixExtension WiX Extension
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Embed PowerShell commands using CDATA
26 |
27 |
28 |
29 |
30 |
31 |
32 |
35 |
36 | The ID for the element.
37 |
38 |
39 |
40 |
41 |
42 | Set to true if script should run as an elevated user
43 |
44 |
45 |
46 |
47 |
48 | Set to true to ignore PowerShell errors
49 |
50 |
51 |
52 |
53 |
54 | Order of script execution. Note that ordering is within the context and type. For example, elevated scripts will run on different context than non-elevated. Defaults to run in line-number order. Files with explicit ordering will be executed before files with implicit ordering
55 |
56 |
57 |
58 |
59 |
60 | Condition on executing the script. For example, 'NOT Installed' or 'REMOVE="ALL"'
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Run a PowerShell script file
79 |
80 |
81 |
82 |
83 |
86 |
87 | The ID for the element.
88 |
89 |
90 |
91 |
92 |
93 | The reference to a PowerShell file
94 |
95 |
96 |
97 |
98 |
99 | The arguments for PowerShell file
100 |
101 |
102 |
103 |
104 |
105 | Set to true if script should run as an elevated user
106 |
107 |
108 |
109 |
110 |
111 | Set to true to ignore PowerShell errors
112 |
113 |
114 |
115 |
116 |
117 | Order of script execution. Note that ordering is within the context and type. For example, elevated scripts will run on different context than non-elevated. Defaults to run in line-number order. Files with explicit ordering will be executed before files with implicit ordering
118 |
119 |
120 |
121 |
122 |
123 | Condition on executing the script. For example, 'NOT Installed' or 'REMOVE="ALL"'
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/PowerShellWixExtension/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using Microsoft.Tools.WindowsInstallerXml;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("PowerShellWixExtension")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("PowerShellWixExtension")]
13 | [assembly: AssemblyCopyright("Copyright © David Gardiner 2014-2021")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7abfedd7-d0f1-489a-a1f4-fb5e3e0bd038")]
24 |
25 | [assembly: AssemblyDefaultWixExtension(typeof(PowerShellWixExtension.PowerShellWixExtension))]
26 |
--------------------------------------------------------------------------------
/PowerShellWixExtension/TableDefinitions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
20 |
21 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
45 |
46 |
49 |
50 |
57 |
58 |
67 |
68 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/Publish-Package.ps1:
--------------------------------------------------------------------------------
1 | # Get latest nupkg
2 |
3 | $nupkg = Get-ChildItem .\Nuget\*.nupkg | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 1
4 |
5 | .\NuGet Push $nupkg -source nuget.org
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerShellWixExtension
2 |
3 | A Wix Extension for running PowerShell scripts
4 |
5 | ## NuGet Package
6 |
7 | [](https://www.nuget.org/packages/PowerShellWixExtension/) [](https://ci.appveyor.com/project/DavidGardiner/powershellwixextension)
8 |
9 | All ready to add to an existing Wix project. Grab the latest version from https://www.nuget.org/packages/PowerShellWixExtension/
10 |
11 | ## Getting Started
12 |
13 | 1. Add a reference to the PowerShellWixExtension.dll in your Wix Setup Project (NuGet package recommended)
14 | 2. Add namespace to .wxs file
15 |
16 | ```xml
17 |
18 |
19 | ```
20 |
21 | 4. To execute a .ps1 file that ships with the project
22 |
23 | ```xml
24 |
25 | ```
26 |
27 | 5. To execute inline script use
28 |
29 | ```xml
30 |
31 |
41 |
42 | ```
43 |
44 | ## Notes
45 |
46 | ### Custom sequences
47 |
48 | You can customise when a set of scripts are run by adding your own `` element inside your `` element. eg.
49 |
50 | ```xml
51 |
52 | NOT Installed
53 |
54 | ```
55 |
56 | The four defined actions are:
57 |
58 | 1. `PowerShellScriptsDeferred`
59 | 2. `PowerShellScriptsElevatedDeferred`
60 | 3. `PowerShellFilesDeferred`
61 | 4. `PowerShellFilesElevatedDeferred`
62 |
63 | ### Inline Scripts
64 |
65 | * Be aware that if your inline script uses square brackets \[ \], you'll need to escape them like [\\[] [\\]] otherwise they will be interpreted as MSI properties (unless that is what you wanted!)
66 |
--------------------------------------------------------------------------------
/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | False
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | False
15 |
16 |
17 |
18 |
19 | False
20 |
21 |
22 |
23 |
24 | False
25 |
26 |
27 |
28 |
29 | False
30 |
31 |
32 |
33 |
34 | False
35 |
36 |
37 |
38 |
39 | False
40 |
41 |
42 |
43 |
44 | False
45 |
46 |
47 |
48 |
49 | False
50 |
51 |
52 |
53 |
54 | False
55 |
56 |
57 |
58 |
59 | False
60 |
61 |
62 |
63 |
64 | False
65 |
66 |
67 |
68 |
69 | False
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | False
80 |
81 |
82 |
83 |
84 | False
85 |
86 |
87 |
88 |
89 | False
90 |
91 |
92 |
93 |
94 | False
95 |
96 |
97 |
98 |
99 | False
100 |
101 |
102 |
103 |
104 | False
105 |
106 |
107 |
108 |
109 | Spaces:False
110 | _$(aaBb)
111 | _$(aaBb)
112 | $(AaBb)
113 | $(AaBb)
114 | $(AaBb)
115 | $(AaBb):$(AA_BB)
116 | 3D A B C FxCop ID IDs OK StyleCop UI X
117 |
118 |
119 |
120 |
121 |
122 |
123 | False
124 |
125 |
126 |
127 |
128 | False
129 |
130 |
131 |
132 |
133 | False
134 |
135 |
136 |
137 |
138 | False
139 |
140 |
141 |
142 |
143 | False
144 |
145 |
146 |
147 |
148 | False
149 |
150 |
151 |
152 |
153 | False
154 |
155 |
156 |
157 |
158 | False
159 |
160 |
161 |
162 |
163 | False
164 |
165 |
166 |
167 |
168 | False
169 |
170 |
171 |
172 |
173 | False
174 |
175 |
176 |
177 |
178 | False
179 |
180 |
181 |
182 |
183 | False
184 |
185 |
186 |
187 |
188 | False
189 |
190 |
191 |
192 |
193 | False
194 |
195 |
196 |
197 |
198 | False
199 |
200 |
201 |
202 |
203 | False
204 |
205 |
206 |
207 |
208 | False
209 |
210 |
211 |
212 |
213 | False
214 |
215 |
216 |
217 |
218 | False
219 |
220 |
221 |
222 |
223 | False
224 |
225 |
226 |
227 |
228 | False
229 |
230 |
231 |
232 |
233 | False
234 |
235 |
236 |
237 |
238 | False
239 |
240 |
241 |
242 |
243 | False
244 |
245 |
246 |
247 |
248 | False
249 |
250 |
251 |
252 |
253 | False
254 |
255 |
256 |
257 |
258 | False
259 |
260 |
261 |
262 |
263 | False
264 |
265 |
266 |
267 |
268 | False
269 |
270 |
271 |
272 |
273 | False
274 |
275 |
276 |
277 |
278 | False
279 |
280 |
281 |
282 |
283 | False
284 |
285 |
286 |
287 |
288 | False
289 |
290 |
291 |
292 |
293 | False
294 |
295 |
296 |
297 |
298 | False
299 |
300 |
301 |
302 |
303 | False
304 |
305 |
306 |
307 |
308 | False
309 |
310 |
311 |
312 |
313 | False
314 |
315 |
316 |
317 |
318 | False
319 |
320 |
321 |
322 |
323 | False
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 | False
334 |
335 |
336 |
337 |
338 | False
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 | False
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 | False
359 |
360 |
361 |
362 |
363 | False
364 |
365 |
366 |
367 |
368 | True
369 |
370 |
371 |
372 |
373 |
374 |
375 |
--------------------------------------------------------------------------------
/Tests/Pester.Tests.ps1:
--------------------------------------------------------------------------------
1 | Import-Module Pester
2 |
3 | $base = $env:GITHUB_WORKSPACE
4 |
5 | if (-not $base) {
6 | $base = "."
7 | }
8 |
9 | Describe 'Inline Scripts' {
10 |
11 | It 'Install' {
12 | 'inlinescript-install.log' | Should -FileContentMatch 'This is an inline script, running non-elevated'
13 | }
14 | }
15 |
16 | Describe 'Scripts' {
17 |
18 | It 'Install' {
19 | 'script-install.log' | Should -FileContentMatch 'This is going to Output'
20 | }
21 | }
--------------------------------------------------------------------------------
/Tests/PowerShellWixInlineScriptTest/PowerShellWixInlineScriptTest.wixproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 3.10
7 | bba07f7f-e4d8-47f7-9a05-4cd6644236c2
8 | 2.0
9 | PowerShellWixInlineScriptTest
10 | Package
11 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
12 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
13 |
14 |
15 | bin\$(Configuration)\
16 | obj\$(Configuration)\
17 | Debug
18 | False
19 | True
20 | True
21 |
22 |
23 | bin\$(Configuration)\
24 | obj\$(Configuration)\
25 | False
26 | True
27 | True
28 |
29 |
30 |
31 |
32 |
33 |
34 | ..\..\Libs\PowerShellWixExtension.dll
35 | PowerShellWixExtension
36 |
37 |
38 | $(WixExtDir)\WixUIExtension.dll
39 | WixUIExtension
40 |
41 |
42 |
43 |
44 |
45 |
46 |
54 |
--------------------------------------------------------------------------------
/Tests/PowerShellWixInlineScriptTest/Product.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | NOT Installed
16 |
17 |
18 |
19 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/Tests/PowerShellWixInlineScriptTest/TextFile1.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Tests/PowerShellWixTest/PowerShellWixTest.wixproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 3.8
7 | 0e852b37-0dd2-4fe9-8e20-123c0040f8ba
8 | 2.0
9 | PowerShellWixTest
10 | Package
11 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
12 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
13 |
14 |
15 | bin\$(Configuration)\
16 | obj\$(Configuration)\
17 | Debug
18 | False
19 | True
20 |
21 |
22 | bin\$(Configuration)\
23 | obj\$(Configuration)\
24 | True
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ..\..\Libs\PowerShellWixExtension.dll
33 | PowerShellWixExtension
34 |
35 |
36 | $(WixExtDir)\WixUIExtension.dll
37 | WixUIExtension
38 |
39 |
40 |
41 |
42 |
43 |
44 |
52 |
--------------------------------------------------------------------------------
/Tests/PowerShellWixTest/Product.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
47 |
48 |
49 |
50 |
59 |
60 |
61 |
62 |
69 |
70 |
71 |
72 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | 1
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/Tests/PowerShellWixTest/ProgressDlg.wxs:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/Tests/PowerShellWixTest/Test.ps1:
--------------------------------------------------------------------------------
1 | param([string] $first)
2 |
3 | $DebugPreference = "Continue"
4 | $VerbosePreference = "Continue"
5 |
6 | Write-Host "Testing Test.ps1 - $first"
7 |
8 | Write-Output "This is going to Output"
9 |
10 | Write-Verbose "This is going to verbose"
11 |
12 | Write-Debug "This is going to Debug"
13 |
14 | Write-Host "Current identity"
15 |
16 | $wid=[System.Security.Principal.WindowsIdentity]::GetCurrent()
17 | $prp=new-object System.Security.Principal.WindowsPrincipal($wid)
18 | $adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator
19 |
20 | Write-Host $wid.Name
21 | Write-Host $prp.IsInRole($adm)
--------------------------------------------------------------------------------
/tables.xsd:
--------------------------------------------------------------------------------
1 |
2 |
10 |
13 |
14 |
15 | Schema for describing table definitions in Windows Installer.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Boolean whether rows in this table create symbols
35 |
36 |
37 |
38 |
39 | Name of table in Windows Installer database
40 |
41 |
42 |
43 |
44 | Specifies if table is virtual or not
45 |
46 |
47 |
48 |
49 | Specifies if the table is a part of the Bootstrapper Application Data manifest
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | Name of column in Windows Installer table
60 |
61 |
62 |
63 |
64 |
65 | Whether this column was added by a transform.
66 |
67 |
68 |
69 |
70 |
71 | Type of column in Windows Installer table
72 |
73 |
74 |
75 |
76 |
77 | Type of column in Windows Installer table
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | Boolean whether column is primary key of Windows Installer table
90 |
91 |
92 |
93 |
94 |
95 | Boolean whether column is nullable in Windows Installer table
96 |
97 |
98 |
99 |
100 |
101 | Boolean whether column is virtual in Windows Installer table
102 |
103 |
104 |
105 |
106 |
107 | Enumeration specifying how column should have the ModuleId appended
108 |
109 |
110 |
111 |
112 |
113 | Set to "yes" in order to allow substitution for localized variables.
114 |
115 |
116 |
117 |
118 |
119 | Minimum value for column in Windows Installer table
120 |
121 |
122 |
123 |
124 |
125 | Maximum value for column in Windows Installer table
126 |
127 |
128 |
129 |
130 |
131 | Foreign key table for column in Windows Installer table
132 |
133 |
134 |
135 |
136 |
137 | Maximum value for column in Windows Installer table
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | Specific column data types for column
150 |
151 |
152 |
153 |
154 |
155 | List of permissible values for the column
156 |
157 |
158 |
159 |
160 |
161 | Description of column
162 |
163 |
164 |
165 |
166 |
167 | Set to "yes" in order to make the idt exporter escape whitespace characters \r, \n, and \t.
168 |
169 |
170 |
171 |
172 |
173 | Set to "yes" in order to make the Intermediate and Output objects wrap their data in a CDATA element to preserve whitespace.
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "3.0",
4 | "publicReleaseRefSpec": [
5 | "^refs/heads/main$",
6 | "^refs/heads/v\\d+(?:\\.\\d+)?$"
7 | ],
8 | "nugetPackageVersion": {
9 | "semVer": 2
10 | },
11 | "cloudBuild": {
12 | "setAllVariables": true,
13 | "buildNumber": {
14 | "enabled": true,
15 | "includeCommitId": {
16 | "when": "always",
17 | "where": "buildMetadata"
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------