Skip to content

Instantly share code, notes, and snippets.

@edyoung
Created September 10, 2022 03:04
Show Gist options
  • Save edyoung/0b6fc325fab41cb69f5edd1d2be883ce to your computer and use it in GitHub Desktop.
Save edyoung/0b6fc325fab41cb69f5edd1d2be883ce to your computer and use it in GitHub Desktop.
Insert a file into an MSI
[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