param( [Parameter(Mandatory = $true)] [string]$SetupExe, [Parameter(Mandatory = $true)] [string]$OutputMsi, [Parameter(Mandatory = $true)] [string]$Version ) $ErrorActionPreference = "Stop" function Find-WixTool($toolName) { $command = Get-Command $toolName -ErrorAction SilentlyContinue if ($command) { return $command.Source } $searchRoots = @( "${env:ProgramFiles(x86)}\WiX Toolset v3.14\bin", "${env:ProgramFiles(x86)}\WiX Toolset v3.11\bin", "${env:ProgramFiles}\WiX Toolset v3.14\bin", "${env:ProgramFiles}\WiX Toolset v3.11\bin" ) foreach ($root in $searchRoots) { $candidate = Join-Path $root "$toolName.exe" if (Test-Path $candidate) { return $candidate } } throw "Could not find $toolName. Install WiX Toolset v3.11 or v3.14 on the Windows build agent." } $rootDir = Split-Path -Parent $PSScriptRoot $wxsPath = Join-Path $rootDir "packaging/windows/farmcontrol-server.wxs" $workDir = Join-Path $env:TEMP "farmcontrol-server-msi" $wixObj = Join-Path $workDir "farmcontrol-server.wixobj" if (Test-Path $workDir) { Remove-Item $workDir -Recurse -Force } New-Item -ItemType Directory -Path $workDir | Out-Null function ConvertTo-WixVersion([string]$rawVersion) { $parts = $rawVersion.Split('.') while ($parts.Count -lt 4) { $parts += '0' } return ($parts[0..3] -join '.') } $candle = Find-WixTool "candle" $light = Find-WixTool "light" $wixVersion = ConvertTo-WixVersion $Version $setupExePath = (Resolve-Path -LiteralPath $SetupExe).Path # Quote -d defines so PowerShell passes them as single args to candle.exe. # Unquoted -dVersion=$Version is parsed incorrectly; paths with spaces also break. $candleArgs = @( '-nologo' '-out' $wixObj "-dVersion=$wixVersion" "-dSetupExe=$setupExePath" $wxsPath ) & $candle @candleArgs $lightArgs = @( '-nologo' '-out' $OutputMsi $wixObj ) & $light @lightArgs if (-not (Test-Path $OutputMsi)) { throw "MSI was not created at $OutputMsi" } Write-Host "Created MSI at $OutputMsi"