Your strategic advantage starts here

Write to the Windows Installer Binary Stream using Powershell

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
Related Posts
3 Comments

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

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

….I’d need more information on the error.

Leave a Reply
Give us a call

Available from 9am to 8pm, Monday to Friday.

Send us a message

Send your message any time you want.

Our usual reply time: 1 Business day
Give us a call

Available from 9am to 8pm, Monday to Friday.

Send us a message

Send your message any time you want.

Our usual reply time: 1 Business day