Monday, November 17, 2008

MSI DLL Custom Actions


In an MSI DLL custom action written with C or C++, the process of writing to the log file is

similar to the VBScript code, except that you use MsiCreateRecord to create the message

record and MsiProcessMessage to pass the record to the running installer.

You begin by creating a C or C++ DLL project in Visual Studio, for example. The C++ code

for this example might look like the following.

#pragma comment(lib, "msi.lib")

#include

#include

#include

// standard MSI DLL custom action signature

UINT __stdcall LoggingTestCpp(MSIHANDLE hInstall)

{

PMSIHANDLE hRecord = MsiCreateRecord(1);

// field 0 is the template

MsiRecordSetString(hRecord, 0, "Log: [1]");

// field 1, to be placed in [1] placeholder

MsiRecordSetString(hRecord, 1, "Calling LoggingTestCpp...");

// send message to running installer

MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hRecord);

return ERROR_SUCCESS;

}

To ensure that the function name is properly exported from the DLL, you can create a .def

file with contents similar to the following:

LIBRARY "LoggingTestCpp" ; DLL name

EXPORTS ; exported function names

LoggingTestCpp

The DLL project in Visual Studio might look similar to the following.

After building the DLL, in InstallShield you can create an MSI DLL custom action, for this

example calling it callLoggingTestCpp, and again scheduling it for immediate execution after

LaunchConditions.

After rebuilding the project and running the MSI with the logging switch, lines similar to the

following should appear in the log file.

Action 25:00:00: callLoggingTestCpp.

Action start 25:00:00: callLoggingTestCpp.

[...lines omitted...]

Log: Calling LoggingTestCpp...

Action ended 25:00:00: callLoggingTestCpp. Return value 1.

For more information, see the MSI help library topic "Windows Installer Logging".