Search code examples
windows-installerinstallshield

How to access the binary table and use in manage code custom actions?


I am trying to execute SQL scripts without using the native InstallShield feature. I have stored SQL files in the binary table (not in support files as its not secure). In the MSI file, I have seen the full path of any binary is replaced with the {binaryname} curly braces names. How can I use binary name with curly braces in others custom actions? Is there any way like we access public properties in custom actions?


Solution

  • I disagree with the notion that the Binary table is any more or less secure than the ISSetupFile table. Both of them store (refernces to) binary streams in their records and can be altered by transforms. Perhaps you mean the ease with which the already-extracted file can be altered? But let's set that aside, and focus on your question.

    The curly braces are a visual notation used by InstallShield in this case to indicate the Binary table reference. It is not a notation recognized by Windows Installer. So you have to find something that is.

    If you want to use the contents of a Binary table record during a custom action, there are two options:

    1. Have that be (part of) the custom action you are executing, having the CustomAction definition itself refer to the binary record. E.g. a type 1 custom action often runs a dll stored in the binary table. You can append extra data to that dll if you control it.
    2. Extract the binary record yourself by querying the table. Note that this can only be done during an immediate-mode custom action, so if you need it during deferred modes (in-script execution) you will have to extract it ahead of time, and either place on the filesystem or smuggle (er, pass) it through CustomActionData.

    If you do the latter in a C++ DLL, the functions you are likely to need include at least the following:

    • MsiGetActiveDatabase
    • MsiDatabaseOpenView: SELECT * FROM `Binary` WHERE `Name`=?
    • MsiViewExecute: pass a record containing the name from within the curly braces
    • MsiViewFetch
    • MsiRecordReadStream
    • MsiCloseHandle

    Since you presumably know the name of your binary table's record, you can hard code it as 'namehere' in place of the ? and skip the record. Note the backticks around table and column names, but apostrophes around the value. Or, for better safety, you can use the question mark placeholder, and populate a record with MsiCreateRecord and MsiRecordSetString.

    Other languages expose the same underlying functionality in different ways. See for example the SDK sample WIStream.vbs for an overview in VBScript, but note that yours will have to run as a custom action instead of an external script.