Kae Travis

Write to the Windows Installer Binary Stream using Powershell

Here’s a small chunk of code from a recent request asking how to write to the Windows Installer binary stream using Powershell:

$msiOpenDatabaseModeReadOnly = 0
$msiOpenDatabaseModeTransact = 1
$windowsInstaller = New-Object -ComObject windowsInstaller.Installer
$pathToMSI = "C:\Users\xxxx\Desktop\AlkaneExample.msi"
$database2 = $windowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $windowsInstaller, @($pathToMSI, $msiOpenDatabaseModeTransact))
$query = "INSERT INTO `Binary` (`Name`,`Data`) Values(?,?)"
$View = $database2.GetType().InvokeMember("OpenView","InvokeMethod",$Null,$database2,($query))
$binaryrecord = $windowsInstaller.GetType().InvokeMember("CreateRecord", "InvokeMethod", $null, $windowsInstaller, 2)  
$binaryrecord.GetType().InvokeMember("StringData", "SetProperty", $null, $binaryrecord, @(1, "AlkaneBinary"))
$fileToStream = "C:\Alkane\AlkaneFile.txt"
$binaryrecord.GetType().InvokeMember("SetStream","InvokeMethod", $null, $binaryrecord, @(2, $fileToStream))
$View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $binaryrecord)
$database2.GetType().InvokeMember("Commit", "InvokeMethod", $null, $database2, $null)
$View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($View) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($binaryrecord) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($database2) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($windowsInstaller) | Out-Null
Write to the Windows Installer Binary Stream using Powershell
Write to the Windows Installer Binary Stream using Powershell

3 thoughts on “Write to the Windows Installer Binary Stream using Powershell

  1. Thanks Kae!!

    It worked perfectly! Just a note for anyone else trying to add a custom action with binary data i.e. VB script, remember to match the name column “AlkaneBinary” in the binary table with the Source column in the custom action table.

    Thanks again.

    Jim

  2. When i try to run the code below, it fails. What am i doing wrong?

    $msiOpenDatabaseModeReadOnly = 0
    $msiOpenDatabaseModeTransact = 1

    $windowsInstaller = New-Object -ComObject windowsInstaller.Installer

    $pathToMSI = “C:\Temp\Test.msi”

    $database = $windowsInstaller.GetType().InvokeMember(“OpenDatabase”, “InvokeMethod”, $null, $windowsInstaller, @($pathToMSI, $msiOpenDatabaseModeTransact))

    $query = “INSERT INTO `Binary` (`Name`,`Data`) Values(?,?)”
    $View = $database.GetType().InvokeMember(“OpenView”, “InvokeMethod”, $Null, $database, ($query))

    $binaryrecord = $windowsInstaller.GetType().InvokeMember(“CreateRecord”, “InvokeMethod”, $null, $windowsInstaller, 2)

    $binaryrecord.GetType().InvokeMember(“StringData”, “SetProperty”, $null, $binaryrecord, @(1, “Test”))

    $fileToStream = “C:\Temp\test.txt”

    $binaryrecord.GetType().InvokeMember(“SetStream”, “InvokeMethod”, $null, $binaryrecord, @(2, $fileToStream))

    $View.GetType().InvokeMember(“Execute”, “InvokeMethod”, $Null, $View, $binaryrecord)

    $View.GetType().InvokeMember(“Close”, “InvokeMethod”, $Null, $View, $Null)

    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($View) | Out-Null

Leave a Reply