Created
September 10, 2022 03:04
-
-
Save edyoung/0b6fc325fab41cb69f5edd1d2be883ce to your computer and use it in GitHub Desktop.
Insert a file into an MSI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[CmdletBinding()] | |
[OutputType( | |
[PSCustomObject] | |
)] | |
param ( | |
[Parameter( | |
Mandatory = $true | |
)] | |
[String] | |
$Path, | |
[Parameter(Mandatory=$true)] | |
[String] | |
$BinaryName, | |
[Parameter(Mandatory=$true)] | |
[String] | |
$InputFile | |
) | |
begin { | |
$windowsInstaller = New-Object -ComObject WindowsInstaller.Installer | |
} | |
process { | |
$InputFile = (Resolve-Path $InputFile).Path | |
Write-Verbose "Updating $BinaryName in $Path with contents of $InputFile" | |
function Get-Property ($Object, $PropertyName, [object[]]$ArgumentList) { | |
return $Object.GetType().InvokeMember($PropertyName, 'Public, Instance, GetProperty', $null, $Object, $ArgumentList) | |
} | |
function Invoke-Method ($Object, $MethodName, $ArgumentList) { | |
return $Object.GetType().InvokeMember($MethodName, 'Public, Instance, InvokeMethod', $null, $Object, $ArgumentList) | |
} | |
$msiReadStreamAnsi = 2 | |
$msiViewModifyUpdate = 2 | |
$pathValue = $path | |
try { | |
$item = Get-Item -Path $pathValue -ErrorAction Stop | |
$database = $windowsInstaller.GetType().InvokeMember( | |
"OpenDatabase", "InvokeMethod", $null, $windowsInstaller, ($item.FullName, 1) | |
) | |
Write-Verbose "Opened Database" | |
$ViewBinary = $database.GetType().InvokeMember( | |
"OpenView", "InvokeMethod", $null, $database, "SELECT Name, Data FROM Binary WHERE Name='$binaryName'" | |
) | |
Write-Verbose "Opened view" | |
$ViewBinary.GetType().InvokeMember( | |
"Execute", "InvokeMethod", $null, $ViewBinary, @() | |
) | |
do { | |
$Binary = $ViewBinary.GetType().InvokeMember( | |
"Fetch", "InvokeMethod", $null, $ViewBinary, @() | |
) | |
if ($Binary) { | |
$Name = Get-Property $Binary StringData 1 | |
$DataSize = Get-Property $Binary DataSize 2 | |
Write-Output "Found Binary: $Name ($DataSize bytes)" | |
Invoke-Method $Binary SetStream @(2, $InputFile) | |
Write-Verbose "Updated record" | |
Invoke-Method $ViewBinary Modify @($msiViewModifyUpdate, $binary) | |
Write-Verbose "Modified view" | |
break; | |
} | |
} | |
while ($Binary) | |
Invoke-Method $ViewBinary Close @() | |
Write-Verbose "Closed View" | |
Invoke-Method $Database Commit @() | |
Write-Verbose "Committed Database" | |
} | |
catch { | |
Write-Error $_ | |
continue | |
} | |
} | |
end { | |
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($windowsInstaller) | |
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($database) | |
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($viewbinary) | |
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($binary) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment