Click to Rate and Give Feedback
MSDN
MSDN Library
Windows Installer
User Interface
 Monitoring an Installation Using Ms...
Monitoring an Installation Using MsiSetExternalUIRecord

Package authors can monitor internal Windows Installer messages through the creation of an executable application that contains both a record-based callback handler to receive the messages and functionality to initiate an installation.

The record-based handler in the following example conforms to the INSTALLUI_HANDLER_RECORD prototype, and a pointer to this callback handler is passed to MsiSetExternalUIRecord function.

//
// ExternalUIRecord.cpp : Defines the entry point for the console application.
//
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
#include <msi.h>
#include <msiquery.h>
#pragma comment(lib, "msi.lib")
#pragma comment(lib, "user32.lib")
#ifndef _WIN32_MSI
#define _WIN32_MSI	310
#endif 

void Usage(LPCTSTR szProgram)
{
_tprintf(TEXT("Usage: %s <path to .MSI package>\n"), szProgram);
return;
}

// In the following snippet, the hRecord parameter is used only
// to format the displayed message. However, because hRecord is 
// a handle to a MSI record, the MSI API could be called to
// obtain information. The external UI handler should not close
// hRecord because the handle belongs to the Windows Installer.

INT CALLBACK UIHandler(LPVOID pvContext, UINT uiMessageType, MSIHANDLE hRecord)
{
INSTALLMESSAGE iMessage = (INSTALLMESSAGE)(0xFF000000 & uiMessageType);
BOOL bMessage = (INSTALLMESSAGE_ERROR == iMessage);
BOOL bFatalExit = (INSTALLMESSAGE_FATALEXIT == iMessage);
BOOL bWarning = (INSTALLMESSAGE_WARNING == iMessage);

if ((bMessage || bFatalExit || bWarning) && hRecord && pvContext)
{
TCHAR rgchMessage[1024];
DWORD dwMessage = sizeof(rgchMessage)/sizeof(TCHAR);
LPTSTR pszMessage = rgchMessage;

UINT uiRet = MsiFormatRecord(*(MSIHANDLE*)pvContext, 
                                 hRecord, pszMessage, &dwMessage);
if (ERROR_MORE_DATA == uiRet)
{
// Allocate a buffer to hold the string and terminating null.
pszMessage = new TCHAR[++dwMessage];
if (!pszMessage)
{
// no memory, return an error
return -1;
}
uiRet = MsiFormatRecord(*(MSIHANDLE*)pvContext, 
                                 hRecord, pszMessage, &dwMessage);
if (ERROR_SUCCESS != uiRet)
{
// Return an error if an unexpected error occurs.
if (rgchMessage != pszMessage)
	delete [] pszMessage;
return -1;
}
}
TCHAR rgchFatalError[] = TEXT("Fatal Error");
TCHAR rgchError[] = TEXT("Error");
TCHAR rgchWarning[] = TEXT("Warning");
TCHAR* pszCaption = NULL;

if (INSTALLMESSAGE_ERROR == iMessage)
	pszCaption = rgchError;
else if (INSTALLMESSAGE_FATALEXIT == iMessage)
	pszCaption = rgchFatalError;
else if (INSTALLMESSAGE_WARNING == iMessage)
	pszCaption = rgchWarning;

int iResponse = MessageBox(NULL, pszMessage, 
                         pszCaption, uiMessageType & 0x00FFFFFF);

if (rgchMessage != pszMessage)
	delete [] pszMessage;
return iResponse;
}

// Signal that the handler handled this message.
return IDOK;
}

// A console application that takes the path to a package,
// installs the package silently, and uses a record based 
// external UI handler to display any error.

int _tmain(int argc, _TCHAR* argv[])
{
UINT uiRet = ERROR_SUCCESS;
MSIHANDLE hProduct = NULL;

if (2 != argc)
{
	// Incorrect command line used.
	Usage(argv[0]);
	uiRet = 1;
	goto End;
}

// Because thid example won't restore the UI level,
// ignore return value.
MsiSetInternalUI(INSTALLUILEVEL_NONE, /* pWnd */ NULL);

uiRet = MsiOpenPackage(argv[1], &hProduct);
if (ERROR_SUCCESS != uiRet)
{
	_tprintf(TEXT("ERROR: Failed to open %s database.\n"), argv[1]);
	uiRet = 1;
	goto End;
}

// set the external UI handler
DWORD dwMessageFilter = INSTALLLOGMODE_FATALEXIT
	   | INSTALLLOGMODE_ERROR | INSTALLLOGMODE_WARNING;

//Pass the pointer to hProduct as the pvContext argument, 
// so that the record based external UI handler
// can use it to format the records we send to it.

uiRet = MsiSetExternalUIRecord(UIHandler, 
              dwMessageFilter, (LPVOID)&hProduct, /* ppuiPrevHandle */ NULL);

if (ERROR_SUCCESS != uiRet)
{
	_tprintf(TEXT("ERROR: Failed to set the external UI handler.\n"));
	uiRet = 1;
	goto End;
}

// Do the default action and install the product.
uiRet = MsiDoAction(hProduct, TEXT(""));

End:
// Close opened resources.
if (hProduct)
	MsiCloseHandle(hProduct);

return ERROR_SUCCESS == uiRet ? 0 : 1;
}
//

Build date: 11/12/2009

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement
Page view tracker