Friday, April 3, 2009

How can I use a custom action to dynamically populate rows in the table?

Immediate custom actions have full access to the Windows Installer database. All you need to do is use the database API to open a view and execute the view. The rest is the SQL query you create that performs an insert of a temporary row in the database. All of this, the APIs + SQL queries, are documented on MSDN in the Windows Installer documentation. If the table needs to be around in memory so that your changes aren't lost when dropped from view, then add a hold count to it (and release the hold count at the end after the requisite action runs).

* MsiGetActiveDatabase
* MsiDatabaseOpenView
* MsiViewExecute

MsiGetActiveDatabase

The MsiGetActiveDatabase function returns the active database for the installation. This function returns a read-only handle that should be closed using MsiCloseHandle.


MSIHANDLE MsiGetActiveDatabase(
MSIHANDLE hInstall
);

Parameters
hInstall
[in] Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct.
Return Values
If the function succeeds, it returns a read-only handle to the database currently in use by the installer. If the function fails, the function returns zero, 0.

Remarks
The MsiGetActiveDatabase function accesses the database in use by the running the installation.

Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle.

For example, if you use code like this:


MSIHANDLE hRec = MsiCreateRecord(3);

Change it to:


PMSIHANDLE hRec = MsiCreateRecord(3);

MsiDatabaseOpenView
The MsiDatabaseOpenView function prepares a database query and creates a view object. This function returns a handle that should be closed using MsiCloseHandle.


UINT MsiDatabaseOpenView(
MSIHANDLE hDatabase,
LPCTSTR szQuery,
MSIHANDLE* phView
);

Parameters
hDatabase
[in] Handle to the database to which you want to open a view object. You can get the handle as described in Obtaining a Database Handle.
szQuery
[in] Specifies a SQL query string for querying the database. For correct syntax, see SQL Syntax.
phView
[out] Pointer to a handle for the returned view.
Return Values
The MsiDatabaseOpenView function returns one of the following values:
ERROR_BAD_QUERY_SYNTAX
An invalid SQL query string was passed to the function.
ERROR_INVALID_HANDLE
An invalid or inactive handle was supplied.
ERROR_SUCCESS
The function succeeded, and the handle is to a view object.
Remarks
The MsiDatabaseOpenView function opens a view object for a database. You must open a view object for a database before performing any execution or fetching.

If an error occurs, you can call MsiGetLastErrorRecord for more information.

Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle.

For example, if you use code like this:


MSIHANDLE hRec = MsiCreateRecord(3);

Change it to:


PMSIHANDLE hRec = MsiCreateRecord(3);

If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord.

MsiViewExecute
The MsiViewExecute function executes a SQL view query and supplies any required parameters. The query uses the question mark token to represent parameters as described in SQL Syntax. The values of these parameters are passed in as the corresponding fields of a parameter record.


UINT MsiViewExecute(
MSIHANDLE hView,
MSIHANDLE hRecord
);

Parameters
hView
[in] Handle to the view upon which to execute the query.
hRecord
[in] Handle to a record that supplies the parameters. This parameter contains values to replace the parameter tokens in the SQL query. It is optional, so hRecord can be zero. For a reference on syntax, see SQL Syntax.
Return Values
ERROR_FUNCTION_FAILED
A view could not be executed.
ERROR_INVALID_HANDLE
An invalid or inactive handle was supplied.
ERROR_SUCCESS
The function succeeded.

Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception.


Remarks
The MsiViewExecute function must be called before any calls to MsiViewFetch.

If the SQL query specifies values with parameter markers (?), a record must be supplied that contains all of the replacement values in the exact order and of compatible data types. When used with INSERT and UPDATE queries all the parameterized values must precede all nonparameterized values.

For example, these queries are valid.

UPDATE {table-list} SET {column}= ? , {column}= {constant}

INSERT INTO {table} ({column-list}) VALUES (?, {constant-list})

However these queries are invalid.

UPDATE {table-list} SET {column}= {constant}, {column}=?

INSERT INTO {table} ({column-list}) VALUES ({constant-list}, ? )

If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord.

No comments:

Post a Comment