Share via


구성 요소 격리

잘 작성된 구성 요소는 호스팅 애플리케이션의 환경을 방해하지 않으며 활성화 컨텍스트를 누출하지도 않습니다. 잘 작성된 구성 요소는 호스팅 애플리케이션의 환경에 의존하지 않고 자체 컨텍스트 관리를 수행합니다.

호스트된 구성 요소의 작성자가 구성 요소에 필요한 다른 어셈블리를 정확히 알 수 있는 가장 좋은 위치에 있습니다. 호스트 애플리케이션을 사용하여 호스트된 구성 요소에 올바른 환경을 제공하는 것은 오류의 원인일 수 있습니다. 대신 모든 종속성을 지정하는 호스트된 구성 요소에 대한 매니페스트를 만든 다음, 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.
}