Generate a Windows Installer transform file (MST) using Powershell

I recently needed to generate a Windows Installer transform file (MST) using Powershell.  I’ve ripped out some excerpts below to demonstrate inserting rows, querying tables, retrieving properties and generating a transform.  Using this example for reference, you should be able to accomplish most tasks using Powershell and the Windows Installer object.

tipTip: Make sure you enclose all table and column names with a double backtick to avoid ‘OpenView,Sql’ errors during OpenView() calls!  By default a single backtick in Powershell acts as an escape character, so we are required to use two of these.

 

19 thoughts on “Generate a Windows Installer transform file (MST) using Powershell

  1. Hi

    The script works well when inserting into other tables. EG “INSERT INTO FeatureComponents (Feature_, Component_) VALUES (‘Program’,’AuditKeys’)”

    But when issuing this as the query.

    “INSERT INTO Registry (Registry, Root, Key, Name, Value, Component_) VALUES (‘SampleReg’, 2, ‘Software\AlkaneTest’, ‘testName’, ‘testValue’, ‘AuditRegKeys’)”

    I get this.

    Exception calling “InvokeMember” with “5” argument(s): “OpenView,Sql”
    At line:61 char:1
    + $View = $database2.GetType().InvokeMember(
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException

    COM object that has been separated from its underlying RCW cannot be used.
    At line:69 char:1
    + $View.GetType().InvokeMember(“Execute”, “InvokeMethod”, $Null, $View, …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OperationStopped: (:) [], InvalidComObjectException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.InvalidComObjectException

    COM object that has been separated from its underlying RCW cannot be used.
    At line:70 char:1
    + $View.GetType().InvokeMember(“Close”, “InvokeMethod”, $Null, $View, $ …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OperationStopped: (:) [], InvalidComObjectException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.InvalidComObjectExceptio

  2. …try enclosing your table names and column names with back-ticks like in the examples…..CREATE TABLE CustomAction ( Action etc.

    I think you’ll find that some columns require this (like the Registry.Key column).  That’s probably where your error is.  It’s probably a best practise to enclose table names and column names like this at all times.

  3. Hi,

    Your post has help me so much updating my automation scripts from vbs to Powershell!

    I have one issue when trying to add a custom action into my mst as the vbscript needs to be added to the binary table and everything I have tried using CreateRecord and SetStream has failed. I have searched everywhere on google and can’t find an answer for powershell.

    Hoping you can point me in the wright direction.

    Thanks,

    Jim

  4. Hi,
    Many thanks for your script, I have tried and it worked wonders.
    But I have a small issue now.
    I am trying to create registry entries in the msi database. I am getting the sql error. Below is my code snippet.
    $queryReg = “INSERT INTO Registry (Registry,Root,Key,Name,Value,Component_) VALUES (‘Branding’,’2′,’Software\test’,’testname’,’1234′,’Branding”
    $ViewReg = $database2.GetType().InvokeMember(“OpenView”,”InvokeMethod”,$Null,$database2,($queryReg))
    $ViewReg.GetType().InvokeMember(“Execute”, “InvokeMethod”, $Null, $ViewReg, $Null) 
    $ViewReg.GetType().InvokeMember(“Close”, “InvokeMethod”, $Null, $ViewReg, $Null)
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ViewReg) | Out-Null
    Error Message:
    Exception calling “InvokeMember” with “5” argument(s): “OpenView,Sql”
    At C:\Scripts\New folder\MSI\Untitled5.ps1:71 char:1
    + $ViewReg = $database2.GetType().InvokeMember(“OpenView”,”InvokeMethod”,$Null,$da …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException

    You cannot call a method on a null-valued expression.
    At C:\Scripts\New folder\MSI\Untitled5.ps1:72 char:1
    + $ViewReg.GetType().InvokeMember(“Execute”, “InvokeMethod”, $Null, $ViewReg, $Nul …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  5. Hi.

    Firstly check the tip in this post for double back ticks.

    Secondly check your SQL statement against the golden rules mentioned here: http://www.alkanesolutions.co.uk/2012/11/30/tutorial-1-introduction-to-msi-scripting-and-golden-rules/

    Your copy and paste doesn’t look to have rendered correctly since your quotes are incorrect and you’re missing a closing bracket.

    (‘Branding’,’2′,’Software\test’,’testname’,’1234′,’Branding”

    should be

    (‘Branding’,’2’,’Software\test’,’testname’,’1234’,’Branding’)”

    Be VERY careful of the quotes and back ticks.  They don’t paste very well in these comments.

     

Leave a Reply

Your email address will not be published. Required fields are marked *