Isolieren von Komponenten
Gut erstellte Komponenten stören weder die Umgebung der Hostanwendung noch geben sie Aktivierungskontexte frei. Gut erstellte Komponenten führen ihre eigene Kontextverwaltung durch, anstatt sich auf die Umgebung der Hostinganwendung zu verlassen.
Der Autor der gehosteten Komponente ist in der besten Position, um genau zu wissen, welche anderen Assemblys die Komponente benötigt. Die Verwendung der Hostanwendung, um die richtige Umgebung für Ihre gehostete Komponente bereitzustellen, ist eine wahrscheinliche Fehlerquelle. Erstellen Sie stattdessen ein Manifest für Die gehostete Komponente, die alle ihre Abhängigkeiten angibt, und kompilieren Sie dann mit ISOLATION _ AWARE _ ENABLED. Dadurch wird sichergestellt, dass externe Aufrufe, die von Ihrer Komponente ausgeführt werden, isoliert sind und die richtigen Versionen verwenden. Da der Aktivierungskontext, den ISOLATION _ AWARE _ ENABLED verwendet, pro DLL ist, kann er sicher in mehreren DLLs verwendet werden, die jeweils ein eigenes Manifest haben, das Abhängigkeiten aufruft.
Wenn es nicht möglich ist, mit ISOLATION AWARE ENABLED zu kompilieren, _ verwenden Sie eine Lösung wie die unter Using _ Callbacks From Hosted Components (Verwenden von Rückrufen aus gehosteten Komponenten).
Sie sollten Ihren eigenen Aktivierungskontext in allen Einstiegspunkten aktivieren, die die Hostinganwendung aufrufen kann, um sicherzustellen, dass Ihre gehostete Komponente vollständig mit dem richtigen Aktivierungskontext ausgeführt wird. Sie können ein C++-Hilfsobjekt verwenden, um das Ändern aller Einstiegspunkte zu vereinfachen. Beispielsweise können Sie eine C++-Klasse wie die folgende verwenden:
#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;
}
}
};
Dies kann dann in Ihrer Komponente verwendet werden, wobei eine globale Variable verwendet wird, um den Aktivierungskontext zu speichern, der auf jedem Einstiegspunkt aktiviert werden soll. Auf diese Weise können Sie Ihre Komponente von Ihrer Hostinganwendung isolieren.
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.
}