포함된 UI 사용
사용자 지정 사용자 인터페이스는 Windows Installer 패키지 내에 포함될 수 있습니다.
사용자 지정 UI를 포함하는 DLL 파일과 사용자 지정 UI에서 사용하는 모든 리소스 파일은 MsiEmbeddedUI 테이블에 나열되어야 합니다. 예를 들어 이 MsiEmbeddedUI 테이블에는 포함된 UI를 포함하는 DLL 파일의 행과 UI에서 사용하는 비트맵 파일의 행이 포함되어 있습니다.
MsiEmbeddedUI | FileName | 특성 | MessageFilter | 데이터 |
---|---|---|---|---|
EmbeddedUI | embedui.dll | 3 | 201359327 | [이진 데이터] |
CustomBitmap | custom.bmp | 0 | [이진 데이터] |
이 예제 embedui.dll에서 사용자 지정 UI 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;
}
}
}