구성 요소 격리
잘 작성된 구성 요소는 호스팅 애플리케이션의 환경을 방해하지 않으며 활성화 컨텍스트를 누출하지도 않습니다. 잘 작성된 구성 요소는 호스팅 애플리케이션의 환경에 의존하지 않고 자체 컨텍스트 관리를 수행합니다.
호스트된 구성 요소의 작성자가 구성 요소에 필요한 다른 어셈블리를 정확히 알 수 있는 가장 좋은 위치에 있습니다. 호스트 애플리케이션을 사용하여 호스트된 구성 요소에 올바른 환경을 제공하는 것은 오류의 원인일 수 있습니다. 대신 모든 종속성을 지정하는 호스트된 구성 요소에 대한 매니페스트를 만든 다음, ISOLATION_AWARE_ENABLED 사용하여 컴파일합니다. 이렇게 하면 구성 요소의 외부 호출이 격리되고 올바른 버전을 사용할 수 있습니다. ISOLATION_AWARE_ENABLED 사용하는 활성화 컨텍스트는 DLL당이므로 종속성을 호출하는 자체 매니페스트가 있는 여러 DLL에서 사용하는 것이 안전합니다.
ISOLATION_AWARE_ENABLED 사용하여 컴파일할 수 없는 경우 호스트된 구성 요소에서 콜백 사용에 표시된 솔루션과 같은 솔루션을 사용합니다.
호스팅 애플리케이션이 호출할 수 있는 모든 진입점에서 사용자 고유의 활성화 컨텍스트를 활성화하여 호스트된 구성 요소가 올바른 활성화 컨텍스트로 완전히 실행되도록 해야 합니다. C++ 도우미 개체를 사용하여 모든 진입점을 쉽게 변경할 수 있습니다. 예를 들어 다음과 같은 C++ 클래스를 사용할 수 있습니다.
#include <windows.h>
class CActivationContext
{
HANDLE m_hActivationContext;
public:
CActivationContext() : m_hActivationContext(INVALID_HANDLE_VALUE)
{
}
VOID Set(HANDLE hActCtx)
{
if (hActCtx != INVALID_HANDLE_VALUE)
AddRefActCtx(hActCtx);
if (m_hActivationContext != INVALID_HANDLE_VALUE)
ReleaseActCtx(m_hActivationContext);
m_hActivationContext = hActCtx;
}
~CActivationContext()
{
if (m_hActivationContext != INVALID_HANDLE_VALUE)
ReleaseActCtx(m_hActivationContext);
}
BOOL Activate(ULONG_PTR &ulpCookie)
{
return ActivateActCtx(m_hActivationContext, &ulpCookie);
}
BOOL Deactivate(ULONG_PTR ulpCookie)
{
return DeactivateActCtx(0, ulpCookie);
}
};
class CActCtxActivator
{
CActivationContext &m_ActCtx;
ULONG_PTR m_Cookie;
bool m_fActivated;
public:
CActCtxActivator(CActivationContext& src, bool fActivate = true)
: m_ActCtx(src), m_Cookie(0), m_fActivated(false)
{
if (fActivate) {
if (src.Activate(m_Cookie))
m_fActivated = true;
}
}
~CActCtxActivator()
{
if (m_fActivated) {
m_ActCtx.Deactivate(m_Cookie);
m_fActivated = false;
}
}
};
그런 다음, 전역 변수를 사용하여 각 진입점에서 활성화해야 하는 활성화 컨텍스트를 저장하는 구성 요소에서 사용할 수 있습니다. 이러한 방식으로 구성 요소를 호스팅 애플리케이션에서 격리할 수 있습니다.
CActivationContext s_GlobalContext;
void MyExportedEntrypoint(void)
{
CActCtxActivator ScopedContext(s_GlobalContext);
// Do whatever work here
// Destructor automatically deactivates the context
}
void MyInitializerFunction()
{
HANDLE hActCtx;
ACTCTX actctx = {sizeof(actctx)};
hActCtx = CreateActCtx(&actctx);
s_GlobalContext.Set(hActCtx);
ReleaseActCtx(hActCtx);
// The static destructor for s_GlobalContext destroys the
// activation context on component unload.
}