次の方法で共有


プロバイダーのアンロード

WMI は、プロバイダーの使用が完了すると、メモリからプロバイダーをアンロードします。 WMI がプロバイダーをアンロードする主な理由は、システム リソースを節約するためです。 そのため、WMI が効率的な方法でプロバイダーをアンロードできるようにするコードを追加する必要があります。 WMI がプロバイダーをアンロードするには、キャッシュ コントロールで指定された間隔からその間隔の 2 倍までの任意の場所が必要です。

WMI は、次のいずれかの方法でプロバイダーをアンロードします。

  • プロバイダーに指定されたタスクが完了した後、プロバイダーをアンロードします。
  • ユーザーがシステムをシャットダウンしたときに、すべてのプロバイダーをすばやくアンロードします。 WMI サービスがコマンド ラインからシャットダウンされると、WMI はインプロセス プロバイダーをアンロードします。

最初のシナリオはより一般的ですが、両方の可能性のためにプロバイダーを記述する必要があります。

このトピックでは、次のセクションについて説明します。

待機状態のプロバイダーのアンロード

WMI は、アイドル状態のプロバイダーをアンロードするときに、次のアクションを実行します。

  • プロバイダーが待機状態かどうかを確かめます。

    WMI は ClearAfter プロパティを使用して、プロバイダーをアンロードする前にプロバイダーがアイドル状態を維持できる期間を決定します。 詳細については、「 プロバイダーのアイドル時間へのアクセス」を参照してください。

  • プロバイダーの Release メソッドを呼び出します。

    プロバイダーが純粋なプロバイダーの場合、 Release はアクティブ メモリからプロバイダーを完全に削除します。 ただし、WMI が Release を呼び出した後も、非pure プロバイダーが引き続き実行される場合があります。

プロバイダーのアイドル時間へのアクセス

プロバイダーがアクティブなままの最小時間は、 ClearAfter プロパティによって決まります。 ClearAfter は、\root 名前空間に__CacheControl WMI システム クラスから派生したクラスのインスタンスにあります。

次の一覧では、プロバイダーのアンロードを制御する __CacheControlから派生するクラスについて説明します。

特定の種類のプロバイダーのキャッシュ コントロール インスタンスの ClearAfter プロパティを編集することで、WMI でプロバイダーが非アクティブな状態を維持できる最小時間を変更できます。 たとえば、プロパティ プロバイダーがアイドル状態を維持できる時間を制限するには、\root 名前空間の__PropertyProviderCacheControl インスタンスの ClearAfter プロパティを編集します。

WMI クライアントでもあるプロバイダーのアンロード

プロバイダーは、実行するために呼び出されたプロバイダー関数を完了した後も、WMI のクライアントのままである必要がある場合があります。 たとえば、プッシュ プロバイダーが WMI にクエリを発行する必要がある場合があります。 詳細については、「 プッシュまたはプルの状態の決定」を参照してください。 この場合、プロバイダーを表す__Win32Provider インスタンスの Pure プロパティを TRUE に設定する必要があります。 Pure プロパティが FALSE に設定されている場合、WMI がプライマリ インターフェイスの Release メソッドを呼び出すときに、すべての未処理のインターフェイス ポイントで IUnknown::Release を呼び出してアンロードを準備します。 詳細については、__Win32Providerの「解説」セクションを参照 してください

次の手順では、プロバイダーのプライマリ インターフェイスのリリース メソッドを実装する方法について説明します。

プロバイダーをアンロードするには

  1. WMI がプロバイダーのプライマリ インターフェイスの Release メソッドを呼び出すときに、WMI に対して保持されているすべてのインターフェイス ポインターを 解放 します。

    通常、プロバイダーは、IWbemProviderInit::Initialize で提供される IWbemServices インターフェイスと IWbemContext インターフェイスへのポインター 保持します。

  2. 関連付けられている__Win32Provider インスタンスの Pure プロパティが FALSE に設定されている場合、WMI が Release を呼び出した後、プロバイダーはクライアント アプリケーションの役割に移行できます。 ただし、WMI はクライアント システムとして動作しているプロバイダーをアンロードできないため、システムのオーバーヘッドが増加します。

    PureTRUE に設定したプロバイダーは、サービス要求にのみ存在します。 そのため、この種類のプロバイダーは、クライアント アプリケーションの役割を引き受けることはできません。WMI は、それをアンロードできます。

シャットダウン中のプロバイダーのアンロード

通常の状況では、「 WMI クライアントでもあるプロバイダーのアンロード 」のガイドラインを使用すると、WMI はプロバイダーを適切にアンロードできます。 ただし、ユーザーがシステムのシャットダウンを選択した場合など、WMI が通常のアンロード 手順を受け入れることができない場合があります。 適切なクリーンアップ戦略を実装するだけでなく、データ ストレージのトランザクション モデルを使用することで、プロバイダーが適切にアンロードされるようにすることができます。

ユーザーはいつでも WMI を停止できます。 このような状況では、WMI はプロバイダーをアンロードしたり、プロセス内プロバイダーで DllCanUnloadNow エントリ ポイントを呼び出したりしません。 さらに、シャットダウン時にインプロセス プロバイダーがメソッド呼び出しの途中にある場合、WMI は呼び出しの途中で実行中のスレッドを終了する可能性があります。 この状況では、WMI は通常、オブジェクトデストラクターなどのクリーンアップを処理するルーチンを呼び出しません。 ほとんどの場合、WMI は DllMain のみを呼び出します。

オペレーティング システムが WMI をシャットダウンすると、システムはインプロセス プロバイダーに割り当てられているすべてのメモリを自動的に解放します。 また、オペレーティング システムは、ファイル ハンドル、ウィンドウ ハンドルなど、プロバイダーが保持するほとんどのリソースも閉じます。 プロバイダーは、これを実現するために特定のアクションを実行する必要はありません。

WMI は呼び出しの途中でシャットダウンする可能性があるため、プロバイダーはデータ ソースを不整合な状態のままにしないでください。 データを不整合な状態のままにすることは、読み取り専用プロバイダーの問題ではありません。 ただし、書き込み機能を持つプロバイダーは、突然の終了後に安全なロールバックを可能にするために、何らかの種類のトランザクション モデルを実装したい場合があります。

オペレーティング システムによって一部の一般的なシステム リソースが解放される場合は、システムによってすべてのリソースが自動的に解放されるわけではありません。 たとえば、オペレーティング システムがソケットまたはデータベース接続を解放しない場合があります。 代わりに、プロバイダーがこのようなリソースを手動でクリーンアップする必要がある場合があります。 これらの問題を回避するためには、プロバイダーをプロセス外で実装するか、後処理コードを追加する方法があります。

最も簡単な解決策は、プロバイダーをプロセス外で実装することです。 WMI がシャットダウンしてもアウトプロセス プロバイダーは強制終了されませんが、WMI は COM タイムアウト後にプロバイダーを解放します。 パフォーマンスよりもクリーンアップと終了の堅牢性の問題を重視するプロバイダーは、アウトプロセスである可能性があります。

プロバイダーにクリーンアップ コードを配置する必要がある場合は、2 つのオプションがあります。 この種のクリーンアップを実行する 1 つの場所は 、DLL をアンロードするときにオペレーティング システムが呼び出す DLL エントリ ポイント関数である DllMain です。 クリーンアップ コードは DllMain に直接追加して、 DLL_PROCESS_DETACHに応答して実行できます。 DllMain でのクリーンアップ コードの実装は、特に MFC や ATL などのプログラミング環境では、配置がやや困難になる場合があります。 詳細については、「MFC 標準 DLL で独自の DllMain を提供する方法」Q148791マイクロソフト サポート技術情報の記事を参照してください。(このリソースは、一部の言語や国または地域では使用できない場合があります)。

または、クリーンアップ コードをグローバル クラスのデストラクターに配置することもできます。 詳細については、「プロバイダーのアンロード」を参照してください。 Windows オペレーティング システムは、ヒープにグローバル オブジェクトを割り当てません。 代わりに、オペレーティング システムは DLL のアンロード中にデストラクターを呼び出します。

WMI のグローバル オブジェクト内に収まる単純なクリーンアップ手順を次に示します。

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

どちらの方法でもクリーンアップ コードで実行できることには、多くの制限があります。 たとえば、暗黙的にリンクされていないスレッドも DLL にも、どのような方法でもアクセスできません。 さらに、どのような状況でも COM 呼び出しを行うことはできません。

名前空間のセキュリティ記述子の設定

プロバイダーのセキュリティ保護

WMI プロバイダーの開発