This repository is built and tested on Windows (WiX + MSI tooling required).
# Restore
nuget restore
# Build all projects (same command used in CI)
msbuild PowerShellWixExtension.sln /p:Configuration=ReleaseIntegration tests are MSI install/uninstall + Pester log assertions:
# Build test MSIs first, then run install/uninstall like CI
Start-Process msiexec.exe -Wait -ArgumentList "/i Tests\PowerShellWixInlineScriptTest\bin\Release\PowerShellWixInlineScriptTest.msi /q /liwearucmopvx $pwd\inlinescript-install.log"
Start-Process msiexec.exe -Wait -ArgumentList "/x Tests\PowerShellWixInlineScriptTest\bin\Release\PowerShellWixInlineScriptTest.msi /q /liwearucmopvx $pwd\inlinescript-uninstall.log"
Start-Process msiexec.exe -Wait -ArgumentList "/i Tests\PowerShellWixTest\bin\Release\PowerShellWixTest.msi /q /liwearucmopvx $pwd\script-install.log"
Start-Process msiexec.exe -Wait -ArgumentList "/x Tests\PowerShellWixTest\bin\Release\PowerShellWixTest.msi /q /liwearucmopvx $pwd\script-uninstall.log"
# Run Pester assertions
Invoke-Pester -Path .\Tests\Pester.Tests.ps1Run a single Pester test:
# Pester 5 style
Invoke-Pester -Path .\Tests\Pester.Tests.ps1 -FullNameFilter "Inline Scripts.Install"
# Pester 4 style
Invoke-Pester -Path .\Tests\Pester.Tests.ps1 -TestName "Install"Linting: there is no separate lint command wired in CI. Settings.StyleCop exists for Visual Studio/StyleCop configuration, but CI runs restore/build/test/pack.
PowerShellWixExtensionis the WiX extension assembly loaded by candle/light:PowerShellCompilerExtensionparses<powershell:Script>and<powershell:File>underProduct/Fragment.- Parsed data is written into custom MSI tables (
PowerShellScripts,PowerShellFiles) defined byTableDefinitions.xml. - The extension embeds and returns
PowerShellLibrary.wixlib, which contains all custom action declarations and default sequencing.
PowerShellLibrary/Library.wxsdefines immediate + deferred install/uninstall custom actions for:- inline scripts vs script files
- elevated vs non-elevated execution
- default sequencing and UI progress text
PowerShellActionsis the custom action runtime:- Immediate actions query MSI tables, evaluate per-row
Condition, serialize payload into deferredCustomActionData, and extend progress ticks. - Deferred actions deserialize payload and execute PowerShell through
PowerShellTask+WixHost*classes, logging via MSI session and honoringIgnoreErrors.
- Immediate actions query MSI tables, evaluate per-row
Tests/*/*.wixprojbuild sample MSIs that consume the extension fromLibs\PowerShellWixExtension.dll;Tests/Pester.Tests.ps1validates behavior by inspecting MSI log output.
- Keep the immediate/deferred pair pattern intact for any new custom action behavior: immediate actions prepare validated data, deferred actions perform execution.
- Inline script payloads are stored as Base64-encoded UTF-16 (
Encoding.Unicode) in thePowerShellScripts.Scriptcolumn; preserve this encoding path end-to-end. - Execution ordering uses
Orderwith implicit default1000000000 + source line; explicit lowerOrdervalues run first within each context/type bucket. Elevated,IgnoreErrors, andConditionare first-class schema/table/runtime fields; changes to extension schema must stay synchronized across:PowerShellWixExtensionSchema.xsdTableDefinitions.xml- compiler parsing (
PowerShellCompilerExtension) - runtime query/execution logic (
PowerShellActions/CustomAction.cs)
- Test WiX projects resolve the extension from
..\..\Libs\PowerShellWixExtension.dll; keepAfterBuildcopy steps in project files working when changing output layout. - For inline scripts in
.wxs, square brackets must be escaped as[\[]and[\]]to avoid MSI property expansion.