Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dobrze utworzone składniki nie zakłócają środowiska aplikacji hostującej ani nie powodują wycieku kontekstów aktywacji. Dobrze utworzone składniki wykonują własne zarządzanie kontekstem, a nie polegają na środowisku aplikacji hostingu.
Autor hostowanego składnika jest w najlepszej sytuacji, aby dokładnie wiedzieć, które inne zespoły są wymagane przez składnik. Poleganie na aplikacji hosta w celu zapewnienia prawidłowego środowiska dla hostowanego składnika jest prawdopodobnym źródłem błędów. Zamiast tego utwórz manifest dla hostowanego składnika, który określa wszystkie jego zależności, a następnie skompiluj przy użyciu ISOLATION_AWARE_ENABLED. Dzięki temu zewnętrzne wywołania wykonywane przez składnik są izolowane i używają poprawnych wersji. Ponieważ kontekst aktywacji używany przez ISOLATION_AWARE_ENABLED jest powiązany z każdą biblioteką DLL, można go bezpiecznie używać w wielu bibliotekach DLL, z których każda ma własny manifest określający zależności.
Jeśli nie można skompilować z ISOLATION_AWARE_ENABLED, należy użyć rozwiązania takiego jak to przedstawione w Korzystanie z wywołań zwrotnych z hostowanych komponentów.
Należy aktywować własny kontekst aktywacji we wszystkich punktach wejścia, które aplikacja hostingowa może wywołać, aby upewnić się, że hostowany składnik działa całkowicie z prawidłowym kontekstem aktywacji. Możesz użyć obiektu pomocniczego języka C++, aby ułatwić zmianę wszystkich punktów wejścia. Można na przykład użyć klasy C++, takiej jak:
#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;
}
}
};
Można go następnie użyć w składniku, używając zmiennej globalnej do przechowywania kontekstu aktywacji, który powinien zostać aktywowany w każdym punkcie wejścia. W ten sposób można odizolować składnik od aplikacji hostingowej.
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.
}