使用內嵌 UI
自訂使用者介面可以內嵌在 Windows Installer 套件中。
包含自訂 UI 的 DLL 檔案,以及自訂 UI 所使用的任何資源檔,都應該列在 MsiEmbeddedUI 資料表中。 例如,這個 MsiEmbeddedUI 資料表包含 DLL 檔案的資料列,其中包含內嵌的 UI,以及 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;
}
}
}