Microsoft Corporation
2006년 8월
적용 대상:
.NET Framework 3.0
개요: .NET Framework 3.0이 필요한 프로그램의 커스터마이징 또는 통합 설치 프로세스에 대해 설명합니다. 이 문서에서는 .NET Framework 3.0 자동 설치 프로세스 실행, 추적 및 취소 방법을 설명합니다.
목차
소개
콜백 함수 훅 업
메시지 수신
메시지 데이터
설치 취소
CSetupWatcher 참고 자료
소개
.NET Framework 3.0은 재배포 가능한 런타임입니다. 통상 .NET Framework 3.0은 응용 프로그램 실행에 필요한 구성요소로서 응용 프로그램의 설치 시에 함께 설치됩니다. .NET Framework 3.0이 필요한 응용 프로그램에서 커스터마이징 또는 통합된 설치 프로세스를 제공하려면, .NET Framework 3.0 설치 프로세스의 실행 및 추적을 사용자에 알리지 않고 실행합니다. 그 동안 사용자에게는 설치 진행 과정을 나타내는 화면을 보여줍니다. 이것은 .NET Framework 3.0 설치 프로세스가 메인 설치 프로세스 감시자로 계속해서 진행 메시지를 송신하여 가능해집니다. 관찰 프로세스는 설치 및 취소를 지정하는 코드를 사용하고, 진행 메시지에 응답할 수 있습니다.
콜백 함수의 훅 업
.NET Framework 3.0을 자동으로 실행 및 추적하기 위해 관찰 프로세스는 .NET Framework 3.0 설치를 실행하기 전에 몇 개의 스텝을 실행하여, 콜백 함수를 훅업해야 합니다. 필요한 지원 코드는 SetupWatcher.h 라는 헤더 파일에 포함되어 있습니다. 이 파일은 SetupWatcher.h (영문)에서 보실 수 있습니다. 다음은 시작 훅업 코드입니다.
#include "SetupWatcher.h"
CSetupWatcher* pSetupWatcher = new CSetupWatcher(L"NetFX3SetupWatcher");
setupWatcher->Connect();
setupWatcher->ReceiveMessages(SetupUIHandler, NULL);
// TODO: launch setup process:
// dotnetfx3setup.exe /q /progress NetFX3SetupWatcher
// Wait for setup process to exit.
Setup Watcher와 설치 프로세스간의 통신은 모두 CSetupWatcher 클래스에 의해 감시되어 처리됩니다. CSetupWatcher 클래스의 새로운 인스턴스를 작성할 경우에는 생성자에게 고유한 이름을 줘야 합니다. 이 이름은 .NET Framework 3.0 설치 프로세스 실행시에 커멘드 라인의 progress 스위치에서도 사용됩니다. 이 인스턴스 이름은 통신을 실시하는 파이프의 이름으로 사용되기 때문에 컴퓨터상에서 고유해야 합니다.
메시지의 감시 및 메시지를 처리하기 위한 콜백 함수의 지정에는 ReceiveMessages 메소드를 사용합니다. ReceiveMessages 메소드는 CSetupWatcher 클래스에 의해 관리되는 새로운 스레드를 생성합니다. 이 스레드는 진행 메시지를 수신하여 메시지를 수신할 때마다 콜백 함수를 호출합니다.
주 CSetupWatcher 메소드 및 그 매개 변수와 반환 코드의 상세한 내용은 이 문서의 마지막 참고 자료 또는 SetupWatcher.h 코드 코멘트를 참조해 주세요.
메시지 수신
CSetupWatcher 콜백 함수 (일반적으로 SetupUIHandler)는 Microsoft Windows 설치 관리자 외부 사용자 인터페이스 (UI) 처리기 (INSTALLUI_HANDLER_RECORD (영문))와 동일한 프로토 타입 및 유사한 시멘틱스를 가집니다.
int SetupUIHandler(void* pvContext, UINT iMessageType,
MSIHANDLE hrecMsg);
메시지 타입 매개 변수에는 Windows 설치 관리자에 의해 정의된 몇 가지 표준 INSTALLMESSAGE_xxx 타입 또는 커스텀 확장자(extension)를 사용할 수 있습니다. 현재의 .NET Framework 3.0 구현의 경우, 메시지 타입은 항상 INSTALLMESSAGE_SUITEPROGRESS 됩니다. 표준 Windows 설치 관리자 메시지는 직접 보내지 않습니다. void 포인터는 eceiveMessages 메소드에 보내진 선택적인 문맥 오브젝트입니다.
메시지는 정수형과 Windows 설치 관리자의 레코드에 의해 구성됩니다. Windows 설치 관리자의 레코드에는 하나의 메시지 및 그 메시지 타입이나 문맥에 데이터 필드가 포함됩니다. 메시지 레코드의 필드0 에는 현재 진행중의 액션을 설명하는 문자열이 보관 됩니다. 메시지는 로컬라이즈 되지 않기 때문에 UI 에는 표시할 수 없는 경우가 있지만, 디버그나 로그 기록에 사용할 수 있습니다. 다른 필드에는 설치 단계에 따라 정수 데이터가 보관 됩니다.
콜백 함수는 INSTALLMESSAGE_SUITEPROGRESS 메시지 응답으로서 표1의 몇 가지 값을 반환해야 합니다.
표1: 콜백 함수의 반환 값
| 반환 값 |
설명 |
| 0 |
메시지가 무시되었거나, 메시지 타입이 인식되지 않았습니다. |
| IDOK |
메시지가 처리되었습니다. |
| IDCANCEL |
설치를 취소해야 합니다. |
메시지 데이터
표 2는 설치 각 단계의 메시지 타입 INSTALLMESSAGE_SUITEPROGRESS 필드에 보관 되는 데이터 목록입니다.
표 2: INSTALLMESSAGE_SUITEPROGRESS 메시지의 데이터
| 단계 |
필드 |
| 제 1 단계
초기화 |
- Field 1: 정수 1. 제 1 단계 (초기화중)를 나타냅니다.
- Field 2: 0 에서 100 까지의 정수. 초기화가 얼마나 완료되었는지 나타냅니다.
|
| 제 2 단계
다운로드 |
- Field 1: 정수2. 제 2 단계 (다운로드 중)를 나타냅니다.
- Field 2: 정수. 지금까지 다운로드 된 KB를 나타냅니다.
- Field 3: 정수. 다운로드 되는 KB의 합계를 나타냅니다.
- Field 4: 정수. 현재의 전송률을 KB/s로 나타내 보입니다.
|
| 제 3 단계
설치 |
- Field 1: 정수3. 제 3 단계 (설치중)를 나타냅니다.
- Field 2: 정수. 타이머 틱으로 사용되어 설치의 현재의 진행 상황을 나타냅니다.
- Field 3: 정수. 설치의 진행 상황을 나타내는 틱의 합계를 나타냅니다.
|
| 롤백(rollback)
(오류인가 취소의 뒤) |
|
설치 취소
.NET Framework 3.0 설치를 임의의 시점에서 취소할 수 없습니다. 설치를 취소하는 경우 관찰 프로세스는 진행 메시지가 송신될 때까지 대기한 후, IDCANCEL을 반환합니다. 다만 진행 메시지 송신은 설치 프로세스의 거의 모든 단계에서 계속해서 진행됩니다.
취소 응답을 수신해도 설치가 즉시 종료되지 않는 경우가 있습니다. 설치 단계에 따라 부분적 또는 전체적인 롤백를 실시하는데 시간이 걸리는 경우도 있습니다. 또 설치가 거의 종료된 경우는 그대로 완료시키는 경우도 있습니다. 프로세스의 종료 코드는 설치가 취소되었는지 (ERROR_INSTALL_USEREXIT) 설치가 완료했는지 (ERROR_SUCCESS / ERROR_SUCCESS_REBOOT_REQUIRED) 또는 오류가 발생했는지를 나타냅니다.
CSetupWatcher 참고 자료
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher //
///////////////////
//
// Facility for hooking up external (local out-of-proc) setup UI using named
// pipes.
// Uses a design similar to MSI's external UI handler (and the same callback
// prototypes), but can be integrated into any kind of setup engine.
//
class CSetupWatcher
{
public:
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher constructor
//
// Creates a new setup watcher instance, for use either by the process watching
// the setup, or by the setup process being watched.
//
// szName - Identifies the setup instance being watched. The watcher and
// the watchee must use the same name. The name should be unique
// enough to avoid conflicting with other instances on the system.
//
// fWatcher - True if the calling process is the watcher process, false if the
// calling process is the setup process being watched.
//
CSetupWatcher(const wchar_t* szName, bool fWatcher=true);
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher destructor
//
// Closes any open handles and frees any allocated memory.
//
~CSetupWatcher();
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::Connect()
//
// Connects the inter-process communication channel.
// (Currently implemented as a named pipe.)
//
// This method must be called first by the watcher process, then by the watched
// setup process. The method does not block; the watcher will asynchronously
// wait for the watched process to make the connection.
//
// Returns: 0 on success, Win32 error code on failure.
//
DWORD Connect();
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::IsConnected()
//
// Checks if the watcher process and setup process are currently connected.
//
bool IsConnected() const;
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::ReceiveMessages()
//
// For use by the watcher process. Watches for messages in the input buffer and
// calls the callback for each one.
//
// This method does not block; it spawns a separate thread to do the work.
//
// pHandler - Callback function to handle any messages received.
//
// pvContext - Optional context pointer to pass to the callback function.
//
// Returns: 0 on success, Win32 error code on failure.
//
DWORD ReceiveMessages(INSTALLUI_HANDLER pHandler, void* pvContext);
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::ReceiveMessages()
//
// For use by the watcher process. Watches for messages in the input buffer and
// calls the callback for each one.
//
// This method does not block; it spawns a separate thread to do the work.
//
// pHandler - Callback function to handle any messages received.
//
// pvContext - Optional context pointer to pass to the callback function.
//
// Returns: 0 on success, Win32 error code on failure.
//
DWORD ReceiveMessages(INSTALLUI_HANDLER_RECORD pHandler, void* pvContext);
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::SendMessage()
//
// For use by the watched setup process. Sends a message to the watcher and
// synchronously waits on a reply, up to the timeout value.
//
// iMessageType - Type of message being sent, typically one of the
// INSTALLMESSAGE_* values, optionally combined with other
// flags.
//
// szMessage - Message string being sent.
//
// pdwReply - [OUT] Receives the reply code from the watcher.
//
// Returns: 0 on success, Win32 error code on failure.
// Returns WAIT_TIMEOUT if no reply was received in time.
//
DWORD SendMessage(UINT iMessageType, const wchar_t* szMessage, DWORD*
pdwReply);
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::SendMessage()
//
// For use by the watched setup process. Sends a message to the watcher and
// synchronously waits on a reply, up to the timeout value.
//
// iMessageType - Type of message being sent, typically one of the
// INSTALLMESSAGE_* values, optionally combined with other
// flags.
//
// hRec - Message record being sent.
//
// pdwReply - [OUT] Receives the reply code from the watcher.
//
// Returns: 0 on success, Win32 error code on failure.
// Returns WAIT_TIMEOUT if no reply was received in time.
//
DWORD SendMessage(UINT iMessageType, MSIHANDLE hRec, DWORD* pdwReply);
///////////////////////////////////////////////////////////////////////////////
// CSetupWatcher::SetReplyTimeout()
//
// For use by the watched setup process. Configures the amount of time to
// wait for a reply to a message. If a reply is not received within that time,
// then the connection is broken.
//
void SetReplyTimeout(DWORD dwMilliseconds);
}