Public/New-MsiTransformFile.ps1
function New-MsiTransformFile { param( [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [IO.FileInfo] $MsiPath, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [IO.FileInfo] $MstPath, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [hashtable] $Properties ) Write-Verbose "[New-MsiTransformFile] Param MsiPath: ${MsiPath}" Write-Verbose "[New-MsiTransformFile] Param MstPath: ${MstPath}" [Msi]::ClearReplacements() [Msi]::ClearAdditions() $msiFileInfo = Get-MsiFileInfo $MsiPath -Properties * $existingProperties = $msiFileInfo.PSObject.Properties.Name foreach ($property in $Properties.GetEnumerator()) { if ($existingProperties -contains $property.Name) { [Msi]::AddReplacement($property.Name, $property.Value) } else { [Msi]::AddAddition($property.Name, $property.Value) } } Write-Verbose "[New-MsiTransformFile] MsiPath: $($msiFileInfo.'.IO.FileInfo')" Write-Verbose "[New-MsiTransformFile] MstPath: ${MstPath}" # Create a new STDOUT for catching assembly output $writer = New-Object IO.StringWriter [Console]::SetOut($writer) # This doesn't write to a PowerShell stream # It writes, but to something else. # Redirect all (*>&1) doesn't catch the output. [Msi]::CreateTransform($msiFileInfo.'.IO.FileInfo', $MstPath) # Store the output and bring back real STDOUT $result = $writer.ToString() $standardOutput = New-Object IO.StreamWriter([Console]::OpenStandardOutput()) $standardOutput.AutoFlush = $true [Console]::SetOut($standardOutput) Write-Verbose "[New-MsiTransformFile] MSI CreateTransform: ${result}" [Collections.ArrayList] $msg = $result.Split(' ') if ($msg[0] -eq 'ERROR') { $msg.RemoveAt(0) Throw ($msg -join ' ') } # $MstPath.Refresh() return $MstPath } |