MsiRecordSetString (msi)
Last changed: -167.100.118.140

.
Summary
Copies a string into the designated field.

C# Signature:

[DllImport("msi.dll", CharSet=CharSet.Unicode)]
static extern int MsiRecordSetString(IntPtr hRecord, int iField, string szValue);

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

The sample application below demonstrates how to use MsiRecordSetString, MsiOpenDatabase, MsiCreateRecord, MsiCloseHandle, MsiDatabaseOpenView, MsiViewExecute, MsiDatabaseCommit, and MsiViewClose in C# to modify a property value in an MSI database. To run it, simply create a new Windows Console application and replace the code that Visual Studio gives you with the code below. You may have to modify the namespace name. The sample as-is requires a valid MSI database named SETUP.msi, with a property named PROPERTY1 in the Property table, to be located in C:\. You can of course change the path to your MSI database in the calls to ChangeMSIProperty() in Main() and use any existing property you wish.

using System;

using System.Globalization;

using System.Runtime.InteropServices;

namespace ConsoleApplication1

{

    /////////////////////////////////////////////////////////////////////////////
    // MsiInstallationSupportException  class
    /////////////////////////////////////////////////////////////////////////////
    public class MsiInstallationSupportException : ApplicationException
    {
    // This class encapsulates and overloads exception handling.
    public MsiInstallationSupportException() : base() { }
    public MsiInstallationSupportException(string message, Exception innerException) : base(message, innerException) { }
    public MsiInstallationSupportException(string message) : base(message) { }
    }

    /////////////////////////////////////////////////////////////////////////////
    // Program class
    /////////////////////////////////////////////////////////////////////////////
    class Program
    {
    //*******************************************
    // This enum contains common MSI error codes.
    //*******************************************
    private enum WINDOWS_MESSAGE_CODES
    {
        ERROR_SUCCESS = 0,
        ERROR_INVALID_PARAMETER = 87,
        ERROR_NO_MORE_ITEMS = 259,
        ERROR_INSTALL_USEREXIT = 1602,
        ERROR_INSTALL_FAILURE = 1603,
        ERROR_BAD_CONFIGURATION = 1610,
        ERROR_INSTALL_IN_PROGRESS = 1618,
        ERROR_INSTALL_SOURCE_ABSENT = 1612,
        ERROR_UNKNOWN_PRODUCT = 1605,
        ERROR_FUNCTION_FAILED = 1627,
        ERROR_INVALID_HANDLE_STATE = 1609,
        ERROR_MORE_DATA = 234,
        ERROR_UNKNOWN_PROPERTY = 1608,
        ERROR_CREATE_FAILED = 1631,
        ERROR_OPEN_FAILED = 110,
        ERROR_BAD_QUERY_SYNTAX = 1615
    }

       //***********************************
       // DllImports for the MSI API's used.
       //***********************************
    [DllImport("msi.dll", SetLastError = true)]
    static extern int MsiOpenDatabase(string szDatabasePath, IntPtr phPersist, out IntPtr phDatabase);

    [DllImport("msi.dll", ExactSpelling = true)]
    static extern IntPtr MsiCreateRecord(uint cParams);

    [DllImport("msi.dll", ExactSpelling = true)]
    static extern int MsiCloseHandle(IntPtr hAny);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiDatabaseOpenViewW(IntPtr hDatabase, [MarshalAs(UnmanagedType.LPWStr)] string szQuery, out IntPtr phView);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiViewExecute(IntPtr hView, IntPtr hRecord);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiDatabaseCommit(IntPtr hDatabase);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiRecordSetString(IntPtr hRecord, int iField, string szValue);

    [DllImport("msi.dll")]
    static extern int MsiViewClose(IntPtr viewhandle);

    //*****************************************
    // Open mode constants for MsiOpenDatabase.
    //*****************************************
    const int MSIDBOPEN_READONLY =     0;  // database open read-only, no persistent changes
    const int MSIDBOPEN_TRANSACT =     1;  // database read/write in transaction mode
    const int MSIDBOPEN_DIRECT =       2;  // database direct read/write without transaction
    const int MSIDBOPEN_CREATE =       3;  // create new database, transact mode read/write
    const int MSIDBOPEN_CREATEDIRECT = 4;  // create new database, direct mode read/write

    //*********************
    // Program entry point.
    //*********************
    static void Main(string[] args)
    {
        ChangeMSIProperty(@"C:\SETUP.msi", "PROPERTY1", "1"); // Set property "PROPERTY1" to a value of 1.

        ChangeMSIProperty(@"C:\SETUP.msi", "PROPERTY1", "0"); // Now set property "PROPERTY1" to a value of 1.
    }

    //***************************************************
    // The method to call to set/change a property value.
    //***************************************************
    static void ChangeMSIProperty(string path, string property, string value)
    {
        // The sql command. Note the "?" placeholder for the value.
        string sql = @"UPDATE Property SET Value = ? WHERE Property = '" + property + "'";
        IntPtr msiHandle = IntPtr.Zero;
        IntPtr msiRecord = IntPtr.Zero;
        IntPtr msiView = IntPtr.Zero;
        int iOpenMode = MSIDBOPEN_DIRECT;
        IntPtr persist = new IntPtr(iOpenMode);

        try
        {
        // Open the database for read/write access.
        WINDOWS_MESSAGE_CODES returnValue = (WINDOWS_MESSAGE_CODES)MsiOpenDatabase(path, persist, out msiHandle);
        if (returnValue != WINDOWS_MESSAGE_CODES.ERROR_SUCCESS)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiOpenDatabase returned error code {0}.", returnValue.ToString()));
            // If the returnValue error code is defined in the enum WINDOWS_MESSAGE_CODES, the exception message will show the enum code name; otherwise it will show the error number.

        // Create a record to be used in tandem with the view below.
        msiRecord = MsiCreateRecord(1);
        if (msiHandle == IntPtr.Zero)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiCreateRecord failed to return a valid record handle."));

        // Set field 1 of your record to the value to set in the database.
        returnValue = (WINDOWS_MESSAGE_CODES)MsiRecordSetString(msiRecord, (int)1, value);
        if (returnValue != WINDOWS_MESSAGE_CODES.ERROR_SUCCESS)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiRecordSetString returned error code {0}.", returnValue.ToString()));

        // Open a view to use to apply the change. Here's where you specify your sql command.
        returnValue = (WINDOWS_MESSAGE_CODES)MsiDatabaseOpenViewW(msiHandle, sql, out msiView);
        if (returnValue != WINDOWS_MESSAGE_CODES.ERROR_SUCCESS)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiDatabaseOpenViewW returned error code {0}.", returnValue.ToString()));

        // Execute the view, passing it the record set. If the property does not exist, it will NOT be created and there will be NO error thrown.
        returnValue = (WINDOWS_MESSAGE_CODES)MsiViewExecute(msiView, msiRecord);
        if (returnValue != WINDOWS_MESSAGE_CODES.ERROR_SUCCESS)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiViewExecute returned error code {0}.", returnValue.ToString()));

        // Close the view.
        returnValue = (WINDOWS_MESSAGE_CODES)MsiViewClose(msiView);
        if (returnValue == WINDOWS_MESSAGE_CODES.ERROR_SUCCESS) // note prior to 7/11/2010, this was != instead of ==, causing MSI to be inconsistent. Commit seems required. Edited by txcraig
        {
            // Commit the changes.
            returnValue = (WINDOWS_MESSAGE_CODES)MsiDatabaseCommit(msiHandle);
            if (returnValue != WINDOWS_MESSAGE_CODES.ERROR_SUCCESS)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiDatabaseCommit returned error code {0}.", returnValue.ToString()));

        }
        else
        {
            // Failed to close the view.
            if (returnValue != WINDOWS_MESSAGE_CODES.ERROR_SUCCESS)
            throw new MsiInstallationSupportException(string.Format(CultureInfo.InvariantCulture, "MsiViewClose returned error code {0}.", returnValue.ToString()));
        }

        }
        finally
        {
        // Close handles or you could get a corrupted database and un-closed handles.
        if (msiRecord != IntPtr.Zero)
            MsiCloseHandle(msiRecord);

        if (msiView != IntPtr.Zero)
            MsiCloseHandle(msiView);

        if (msiHandle != IntPtr.Zero)
            MsiCloseHandle(msiHandle);
        }
    }
    }

}

Alternative Managed API:

MSI interop library

http://sourceforge.net/project/showfiles.php?group_id=40188&package_id=110212

Documentation