使用嵌入式 UI
自定义用户界面可以嵌入到 Windows Installer 程序包中。
包含自定义 UI 的 DLL 文件以及自定义 UI 使用的任何资源文件都应列在 MsiEmbeddedUI 表中。 例如,此 MsiEmbeddedUI 表包含其中包含嵌入式 UI 的 DLL 文件中的行和由 UI 使用的位图文件中的行。
MsiEmbeddedUI | FileName | 特性 | MessageFilter | 数据 |
---|---|---|---|---|
EmbeddedUI | embedui.dll | 3 | 201359327 | [二进制数据] |
CustomBitmap | custom.bmp | 0 | [二进制数据] |
自定义 UI DLL(在此示例中为 embedui.dll)应导出用户定义的 InitializeEmbeddedUI、EmbeddedUIHandler 和 ShutdownEmbeddedUI 函数。 以下示例代码阐释了这些函数。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <msi.h>
#include <msiquery.h>
#include <Aclapi.h>
#include <strsafe.h>
#pragma comment(lib, "msi.lib")
#define cchGUID 38
int __stdcall InitializeEmbeddedUI(MSIHANDLE hInstall,
LPCWSTR szResourcePath, LPDWORD pdwInternalUILevel)
{
// The hInstall handle is only valid within this function and
// can be used to get or set properties. The handle
// does not need to be explicitly closed.
WCHAR szProductCode[cchGUID+1];
DWORD cchProductCode = ARRAYSIZE(szProductCode);
UINT uiStat = MsiGetProperty(hInstall, L"ProductCode",
szProductCode, &cchProductCode);
UNREFERENCED_PARAMETER(szResourcePath);
if (ERROR_SUCCESS != uiStat)
{
// The installation should fail.
return ERROR_INSTALL_FAILURE;
}
WCHAR* szReinstall = NULL;
DWORD cchReinstall = 0;
uiStat = MsiGetProperty(hInstall, TEXT("REINSTALL"),
szReinstall, &cchReinstall);
if (ERROR_MORE_DATA == uiStat)
{
++cchProductCode; // Add 1 for terminating null character.
szReinstall = new WCHAR[cchReinstall];
if (szReinstall)
{
uiStat = MsiGetProperty(hInstall, L"REINSTALL",
szReinstall, &cchReinstall);
}
}
if (ERROR_SUCCESS != uiStat)
{
if (szReinstall != NULL)
delete [] szReinstall;
// This installation should fail.
return ERROR_INSTALL_FAILURE;
}
if (INSTALLSTATE_DEFAULT != MsiQueryProductState(szProductCode))
{
if (INSTALLUILEVEL_BASIC == *pdwInternalUILevel)
{
// Insert the custom UI used by basic installation here.
}
else
{
// Insert the custom UI used by full installation here.
}
}
else if (szReinstall && szReinstall[0])
{
// Reinstall the UI sequence.
}
else
{
// This is a maintenance installation. Remove the UI sequence.
MsiSetProperty(hInstall, TEXT("REMOVE"), TEXT("ALL"));
}
if (szProductCode)
delete [] szReinstall;
// Setting the internal UI level to none specifies that
// no authored UI should run.
*pdwInternalUILevel = INSTALLUILEVEL_NONE;
return 0;
}
DWORD __stdcall ShutdownEmbeddedUI()
{
// ShutdownEmbeddedUI is optional. It can allow the embedded UI
// to perform any cleanup. After this call, the embedded UI
// should not receive any additional callbacks.
return 0;
}
INT __stdcall EmbeddedUIHandler(UINT iMessageType, MSIHANDLE hRecord)
{
// This function is similar to the MsiSetExternalUIRecord callback.
INSTALLMESSAGE mt;
UINT uiFlags;
UNREFERENCED_PARAMETER(hRecord);
mt = (INSTALLMESSAGE) (0xFF000000 & (UINT) iMessageType);
uiFlags = 0x00FFFFFF & iMessageType;
switch (mt)
{
case INSTALLMESSAGE_FATALEXIT:
{
return IDOK;
}
case INSTALLMESSAGE_ERROR:
{
return IDOK;
}
case INSTALLMESSAGE_WARNING:
{
return IDOK;
}
case INSTALLMESSAGE_FILESINUSE:
{
return IDOK;
}
case INSTALLMESSAGE_RESOLVESOURCE:
{
return IDOK;
}
case INSTALLMESSAGE_USER:
{
return IDOK;
}
case INSTALLMESSAGE_INFO:
{
return IDOK;
}
case INSTALLMESSAGE_OUTOFDISKSPACE:
{
return IDOK;
}
case INSTALLMESSAGE_ACTIONSTART:
{
return IDOK;
}
case INSTALLMESSAGE_ACTIONDATA:
{
return IDOK;
}
case INSTALLMESSAGE_PROGRESS:
{
return IDOK;
}
case INSTALLMESSAGE_SHOWDIALOG:
{
return IDOK;
}
case INSTALLMESSAGE_COMMONDATA:
{
return IDOK;
}
case INSTALLMESSAGE_INSTALLSTART:
{
// This message is sent when the Install begins.
// Record contains the ProductName and ProductCode
return IDOK;
}
case INSTALLMESSAGE_INSTALLEND:
{
// This message is sent when the Install ends.
// Record contains the ProductName and ProductCode
// and return value of the installation.
return IDOK;
}
default:
{
return 0;
}
}
}