Compartilhar via


Monitoramento de uma instalação usando MsiSetExternalUIRecord

Os autores de pacotes podem monitorar mensagens internas do Windows Installer por meio da criação de um aplicativo executável que contém um manipulador de retorno de chamada baseado em registro para receber as mensagens e a funcionalidade para iniciar uma instalação.

O manipulador baseado em registro no exemplo a seguir está em conformidade com o protótipo INSTALLUI_HANDLER_RECORD e um ponteiro para esse manipulador de retorno de chamada é passado para a função MsiSetExternalUIRecord.

//
// 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;
}
//