Mengisolasi Komponen

Komponen yang ditulis dengan baik tidak mengganggu lingkungan aplikasi hosting, juga tidak membocorkan konteks aktivasi. Komponen yang ditulis dengan baik melakukan manajemen konteks mereka sendiri daripada mengandalkan lingkungan aplikasi hosting.

Penulis komponen yang dihosting berada dalam posisi terbaik untuk mengetahui dengan tepat rakitan lain mana yang dibutuhkan komponen. Mengandalkan aplikasi host untuk menyediakan lingkungan yang benar untuk komponen yang dihosting adalah sumber kesalahan yang mungkin terjadi. Sebagai gantinya, buat manifes untuk komponen yang dihosting yang menentukan semua dependensinya, lalu kompilasi menggunakan ISOLATION_AWARE_ENABLED. Ini memastikan bahwa panggilan luar yang dilakukan oleh komponen Anda terisolasi dan menggunakan versi yang benar. Karena konteks aktivasi yang ISOLATION_AWARE_ENABLED gunakan adalah per DLL, aman untuk digunakan dalam beberapa DLL, masing-masing dengan manifes mereka sendiri yang memanggil dependensi.

Jika tidak dimungkinkan untuk dikompilasi dengan ISOLATION_AWARE_ENABLED, maka gunakan solusi seperti yang disajikan dalam Menggunakan Panggilan Balik Dari Komponen yang Dihosting.

Anda harus mengaktifkan konteks aktivasi Anda sendiri di semua titik masuk yang dapat dipanggil aplikasi hosting untuk memastikan bahwa komponen yang dihosting berjalan sepenuhnya dengan konteks aktivasi yang benar. Anda dapat menggunakan objek pembantu C++ untuk memfasilitasi perubahan semua titik masuk. Misalnya, Anda dapat menggunakan kelas C++ seperti berikut ini:

#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;
        }
    }
};

Ini kemudian dapat digunakan dalam komponen Anda, menggunakan variabel global untuk menyimpan konteks aktivasi yang harus diaktifkan pada setiap titik masuk. Dengan cara ini, Anda dapat mengisolasi komponen Anda dari aplikasi hosting Anda.

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.
}