Entladen eines Anbieters

Nachdem WMI mit einem Anbieter abgeschlossen wurde, wird der Anbieter aus dem Arbeitsspeicher entladen. Der Hauptgrund, warum WMI einen Anbieter entlädt, ist die Einsparung von Systemressourcen. Daher müssen Sie Code hinzufügen, mit dem WMI Ihren Anbieter effizient entladen kann. Das Entladen eines Anbieters durch WMI dauert zwischen dem in der Cachesteuerung angegebenen Intervall und dem Doppelten dieses Intervalls.

WMI entlädt einen Anbieter auf eine der folgenden Weisen:

  • Einen Anbieter entladen, nachdem der Anbieter die ihm übertragenen Aufgaben abgeschlossen hat.
  • Alle Anbieter schnell entladen, wenn der Benutzer das System herunterfährt. Beachten Sie, dass WMI prozessinterne Anbieter entlädt, wenn der WMI-Dienst über die Befehlszeile heruntergefahren wird.

Obwohl das erste Szenario häufiger vorkommt, müssen Sie Ihren Anbieter für beide Möglichkeiten schreiben.

In diesem Thema werden die folgenden Abschnitte behandelt:

Entladen eines Leerlaufanbieters

WMI führt die folgenden Aktionen aus, wenn ein Leerlaufanbieter entladen wird:

  • Bestimmt, ob sich der Anbieter im Leerlauf befindet.

    WMI verwendet die ClearAfter-Eigenschaft, um zu bestimmen, wie lange ein Anbieter vor dem Entladen dieses Anbieters im Leerlauf bleiben darf. Weitere Informationen finden Sie unter Zugreifen auf die Leerlaufzeit für einen Anbieter.

  • Ruft die Release-Methode des Anbieters auf.

    Wenn der Anbieter ein Pure-Anbieter war, wird der Anbieter mit der Release-Methode vollständig aus dem aktiven Arbeitsspeicher entfernt. Ein Nicht-Pure-Anbieter kann jedoch weiterhin ausgeführt werden, nachdem WMI die Release-Methode aufgerufen hat.

Zugreifen auf die Leerlaufzeit eines Anbieters

Die Mindestdauer, die ein Anbieter aktiv bleibt, wird von der ClearAfter-Eigenschaft bestimmt. Sie finden die ClearAfter-Eigenschaft in Instanzen von Klassen, die von der WMI-Systemklasse __CacheControl im \root-Namespace abgeleitet sind.

In der folgenden Liste werden die Klassen beschrieben, die von __CacheControl abgeleitet sind, womit das Entladen des Anbieters gesteuert wird:

Sie können die Mindestdauer ändern, die WMI einem Anbieter erlaubt, inaktiv zu bleiben, indem Sie die ClearAfter-Eigenschaft in der Cachesteuerungsinstanz für einen bestimmten Anbietertyp bearbeiten. Um beispielsweise die Dauer des Leerlaufs eines Eigenschaftenanbieters zu begrenzen, müssen Sie die ClearAfter-Eigenschaft einer __PropertyProviderCacheControl-Instanz im \root-Namespace bearbeiten.

Entladen eines Anbieters, der auch ein WMI-Client ist

Ihr Anbieter muss möglicherweise ein Client von WMI bleiben, nachdem er die Anbieteraufgaben erledigt hat, für die er aufgerufen wurde. Beispielsweise muss ein Pushanbieter möglicherweise Abfragen an WMI richten. Weitere Informationen finden Sie unter Bestimmen des Push- oder Pullstatus. In diesem Fall muss die Pure-Eigenschaft der __Win32Provider-Instanz, die den Anbieter darstellt, auf TRUE festgelegt werden. Wenn die Pure-Eigenschaft auf FALSE festgelegt ist, bereitet der Anbieter das Entladen vor, indem er IUnknown::Release für alle ausstehenden Schnittstellenpunkte aufruft, wenn WMI die Release-Methode seiner primären Schnittstelle aufruft. Weitere Informationen finden Sie im Abschnitt mit Hinweisen unter __Win32Provider.

Im folgenden Verfahren wird beschrieben, wie Sie eine Release-Methode für die primäre Schnittstelle Ihres Anbieters implementieren.

So entladen Sie einen Anbieter

  1. Geben Sie alle Schnittstellenzeiger für WMI frei, wenn WMI die Release-Methode der primären Schnittstelle Ihres Anbieters aufruft.

    In der Regel enthält ein Anbieter Zeiger auf die Schnittstellen IWbemServices und IWbemContext, die in IWbemProviderInit::Initialize bereitgestellt werden.

  2. Wenn die Pure-Eigenschaft in der zugeordneten __Win32Provider-Instanz auf FALSE festgelegt ist, kann der Anbieter die Rolle einer Clientanwendung übernehmen, nachdem WMI die Release-Methode aufgerufen hat. WMI kann jedoch keinen Anbieter entladen, der als Clientsystem betrieben wird, was den Systemaufwand erhöht.

    Ein Anbieter, bei dem die Pure-Eigenschaft auf TRUE festgelegt ist, dient ausschließlich zum Erfüllen von Anforderungen. Daher kann dieser Anbietertyp nicht die Rolle einer Clientanwendung übernehmen, und WMI kann ihn entladen.

Entladen eines Anbieters während des Herunterfahrens

Unter normalen Umständen ermöglichen Richtlinien unter Entladen eines Anbieters, der auch ein WMI-Client ist WMI das ordnungsgemäße Entladen Ihres Anbieters. Es kann jedoch vorkommen, dass WMI die normalen Entladevorgänge nicht einleiten kann, z. B. wenn der Benutzer sich entschließt, das System herunterzufahren. Mithilfe eines Transaktionsmodells für die Datenspeicherung können Sie zusätzlich zur Implementierung einer geeigneten Bereinigungsstrategie sicherstellen, dass Ihr Anbieter ordnungsgemäß entladen wird.

Der Benutzer kann WMI jederzeit beenden. In einer solchen Situation entlädt WMI keine Anbieter und ruft auch nicht den Einstiegspunkt DllCanUnloadNow für einen beliebigen prozessinternen Anbieter auf. Wenn sich darüber hinaus ein prozessinterner Anbieter zum Zeitpunkt des Herunterfahrens inmitten eines Methodenaufrufs befindet, kann WMI den ausführenden Thread möglicherweise mitten im Aufruf beenden. In diesem Fall ruft WMI keine Routinen auf, die normalerweise für die Bereinigung zuständig sind, wie z. B. einen Objektdestruktor. WMI ruft höchstens nur DllMain auf.

Wenn das Betriebssystem WMI herunterfährt, gibt das System automatisch den gesamten Arbeitsspeicher frei, der einem prozessinternen Anbieter zugeordnet ist. Das Betriebssystem schließt auch die meisten im Besitz des Anbieters befindlichen Ressourcen, wie z. B. Datei- und Fensterhandles usw. Der Anbieter muss keine spezifischen Maßnahmen ergreifen, um dies zu ermöglichen.

Da WMI mitten in einem Aufruf heruntergefahren werden kann, darf ein Anbieter Datenquellen nicht in einem inkonsistenten Zustand belassen. Wenn Sie Ihre Daten in einem inkonsistenten Zustand belassen, ist das für schreibgeschützte Anbieter kein Problem. Anbieter mit Schreibfunktionen möchten jedoch möglicherweise eine Art Transaktionsmodell implementieren, um nach einer abrupten Beendigung ein sicheres Rollback zu ermöglichen.

Das Betriebssystem kann zwar einige allgemeine Systemressourcen freigeben, aber das System gibt nicht automatisch alle Ressourcen frei. Das Betriebssystem gibt beispielsweise eine Socket- oder Datenbankverbindung nicht frei. Stattdessen muss der Anbieter diese Ressourcen möglicherweise manuell bereinigen. Um diese Probleme zu vermeiden, können Sie entweder Ihren Anbieter prozessextern implementieren oder Bereinigungscode hinzufügen.

Die einfachste Lösung besteht darin, Ihren Anbieter prozessextern zu implementieren. Ein prozessexterner Anbieter wird nicht beendet, wenn WMI heruntergefahren wird, obwohl WMI den Anbieter nach einem COM-Timeout freigibt. Anbieter, für die Probleme der Bereinigung und Beendigung wichtiger sind als die Leistung, sind möglicherweise prozessextern.

Wenn Sie Bereinigungscode in Ihrem Anbieter platzieren müssen, haben Sie zwei Möglichkeiten. Eine Stelle für diese Art von Bereinigung ist DllMain, die DLL-Einstiegspunktfunktion, die das Betriebssystem beim Entladen der DLL aufruft. Bereinigungscode kann DllMain direkt hinzugefügt werden und als Reaktion auf DLL_PROCESS_DETACH ausgeführt werden. Die Implementierung von Bereinigungscode in DllMain kann etwas schwierig sein, insbesondere in Programmierumgebungen wie MFC oder ATL. Weitere Informationen finden Sie im Microsoft Knowledge Base-Artikel Q148791 How to Provide Your Own DllMain in an MFC Regular DLL. (Diese Ressource ist in einigen Sprachen und Ländern oder Regionen möglicherweise nicht verfügbar.)

Alternativ können Sie den Bereinigungscode auch im Destruktor einer globalen Klasse platzieren. Weitere Informationen finden Sie unter „Entladen eines Anbieters“. Das Windows-Betriebssystem teilt dem Heap keine globalen Objekte zu. Stattdessen ruft das Betriebssystem die Destruktoren während der DLL-Entladung auf.

Es folgt eine einfache Bereinigungsprozedur, die sich in ein globales Objekt für WMI einfügen lässt.

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

Es gibt viele Einschränkungen, was im Bereinigungscode mit beiden Ansätzen erreicht werden kann. Beispielsweise kann weder auf Threads noch auf DLLs zugegriffen werden, die nicht implizit verknüpft sind. Darüber hinaus können Sie unter keinen Umständen COM-Aufrufe tätigen.

Festlegen von Sicherheitsbeschreibungen für Namespaces

Schützen Ihres Anbieters

Entwickeln eines WMI-Anbieters