共用方式為


卸載提供者

WMI 在完成使用提供者後,會將其從記憶體中卸載。 WMI 卸除提供者的主要原因是節省系統資源。 因此,您必須新增程式碼,以便讓WMI能以有效的方式卸載您的提供者。 它需要大約從快取控件中指定的時間間隔到該間隔的兩倍時間,WMI 才會卸載提供者。

WMI 會以下列其中一種方式卸除提供者:

  • 在提供者完成其工作後,卸除提供者。
  • 當使用者關閉系統時,快速卸除所有提供者。 請注意,當 WMI 服務從命令行關閉時,WMI 會卸除同進程提供者。

雖然第一個情境比較常見,但您必須為這兩種可能性編寫您的供應商。

本主題將討論下列各節:

卸除閑置提供者

WMI 會在卸除閑置提供者時執行下列動作:

  • 判斷提供者是否閑置。

    WMI 會使用 ClearAfter 屬性來判斷提供者在卸除該提供者之前可能會閑置多久。 如需詳細資訊,請參閱 存取提供者閑置時間

  • 呼叫提供者的 Release 方法。

    如果提供者是純提供者,則 Release 完全從活動記憶體中移除提供者。 不過,在 WMI 呼叫 Release之後,非純粹提供者可能會繼續執行。

存取提供者的空檔時間

提供者保持活躍狀態的最短時間由 ClearAfter 屬性所決定。 您可以在 \root 命名空間中,衍生自 WMI 系統類別 __CacheControl 的類別實例中找到 ClearAfter

下列清單描述從 __CacheControl衍生出來的類別,這些類別用於控制提供者卸除:

您可以編輯快取控件實例中特定提供者類型中的 ClearAfter 屬性,以變更 WMI 允許提供者保持非使用中的時間下限。 例如,若要限制屬性提供者可以保持閑置的時間量,您可以在 \root 命名空間中編輯 __PropertyProviderCacheControl 實例的 ClearAfter 屬性。

卸載同時作為 WMI 用戶端的提供者

您的提供者在完成其被呼叫的功能後,可能需要繼續擔任 WMI 的用戶端。 例如,推送提供者可能需要對WMI發出查詢。 如需詳細資訊,請參閱 判斷推送或提取狀態。 在這種情況下,表示提供者之 __Win32Provider 實體的 Pure 屬性應該設定為 TRUE。 如果將 Pure 屬性設定為 FALSE,當 WMI 呼叫其主要介面的 Release 方法時,提供者會通過在所有有效介面上呼叫 IUnknown::Release 來準備卸載。 如需詳細資訊,請參閱 __Win32Provider中的備註一節。

下列程序說明如何為提供者的主要介面實作發行方法。

卸除提供者

  1. 當 WMI 呼叫提供者主要介面的 Release 方法時,釋放針對 WMI 保留的所有介面指標。

    一般而言,提供者會保存 IWbemServicesIWbemContext 介面,這些介面是在 IWbemProviderInit::Initialize中提供的指標。

  2. 如果相關聯 __Win32Provider 實例中的 Pure 屬性設定為 FALSE,提供者可以在 WMI 呼叫 Release之後轉換為用戶端應用程式的角色。 不過,WMI 無法卸除以客戶端系統運作的提供者,這會增加系統負荷。

    被設為 TRUE 時,提供者僅存在於處理服務請求。 因此,這種類型的提供者無法承擔用戶端應用程式的角色,WMI 可以卸除它。

在關機期間卸除提供者

在正常情況下,使用 卸除也是 WMI 用戶端 的提供者中的指導方針可讓 WMI 正確卸載您的提供者。 不過,您可能會遇到 WMI 無法執行正常卸載程序的情況,例如當使用者選擇關閉系統時。 通過使用資料儲存的交易模型,並實施良好的清除策略,您可以確保服務提供者已正確卸載。

用戶可以隨時停止 WMI。 在這種情況下,WMI 不會卸除任何提供者,也不會在任何內部進程提供者上呼叫 DllCanUnloadNow 函數入口點。 此外,如果進程內提供者在系統關機時正執行方法呼叫,WMI 可能會在呼叫過程中終止正在執行的線程。 在此情況下,WMI 不會呼叫通常處理清除的例程,例如對象解構函式。 WMI 最多只會呼叫 DllMain

當作業系統關閉 WMI 時,系統會自動釋放配置給進程內提供者的所有記憶體。 作業系統也會關閉提供者持有的大部分資源,例如檔案控制代碼、視窗控制代碼等。 提供者不需要採取任何特定動作,才會發生此情況。

因為 WMI 可能會在呼叫中間關閉,提供者不應該讓數據源處於不一致的狀態。 數據處於不一致的狀態對唯讀提供者來說不是問題。 不過,具有寫入功能的提供者可能會想要實作某種交易模型,以在突然終止之後允許安全回復。

雖然作系統可能會釋放某些一般系統資源,但系統不會自動釋放所有資源。 例如,作業系統可能不會釋放套接字或資料庫連線。 相反地,提供者可能需要手動清除這類資源。 若要避免這些問題,您可以將提供者實作為進程外,或是新增清理程式碼。

最簡單的解決方案是實作您的提供者外部進程。 當 WMI 關閉時,流程外的提供者不會被終止;不過,WMI 會在 COM 逾時後釋放提供者。 對於那些認為清除和終止的健全性問題比效能更重要的提供者來說,他們可能會在外部進行處理。

如果您必須在供應者中放置清理程式碼,您有兩個選項。 執行這類清除的其中一個位置是 DllMain,這是作業系統在卸除 DLL 時會呼叫的 DLL 入口點函式。 清除程式代碼可以直接新增至 dllMain ,以回應 DLL_PROCESS_DETACH。 在 DllMain 中實作清除程式代碼可能有點困難,特別是在 MFC 或 ATL 等程式設計環境中。 如需詳細資訊,請參閱Microsoft知識庫文章Q148791如何在 MFC 一般 DLL 中提供您自己的 DllMain。“ (某些語言和國家或地區可能無法使用此資源。

或者,您也可以將清除程序代碼放在全域類別的解構函式中。 如需詳細資訊,請參閱卸除提供者。 Windows作業系統不會在堆疊上配置全域物件。 相反地,作業系統會在 DLL 卸載期間呼叫解構函式。

以下是一個簡單的清除程式,可放入WMI的全域物件內。

class CMyCleanup
{
    ~CMyCleanup()
    {
        CloseHandle(m_hOpenFile);
        CloseDatabaseConnection(g_hDatabase);
    }
} g_Cleanup;

使用任一種方法,對清除程式碼中可以執行的動作有許多限制。 例如,無法以任何方式存取未隱含連結的線程和任何 DLL。 此外,在任何情況下,您都無法進行 COM 呼叫。

設定 Namepace 安全性描述元

保護您的提供者

開發 WMI 提供者