隔離元件
撰寫良好的元件不會干擾主控應用程式的環境,也不會洩漏啟用內容。 撰寫良好的元件會執行自己的上下文管理,而不是依賴宿主應用程式的環境。
受託元件的作者最知道其所需的其他組件。 依賴主應用程式來為您的受託元件提供正確的環境容易導致錯誤。 相反地,請為裝載的元件建立指令清單,以指定其所有相依性,然後使用 ISOLATION_AWARE_ENABLED進行編譯。 這可確保元件所進行的外部呼叫會隔離,並使用正確的版本。 因為 ISOLATION_AWARE_ENABLED 使用的激活內容是個別 DLL 的,因此在多個 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.
}