Поделиться через


Выгрузка поставщика

После завершения работы WMI с поставщиком, он выгружает поставщика из памяти. Основная причина, по которой WMI выгружает провайдера, заключается в экономии системных ресурсов. Поэтому необходимо добавить код, который позволит WMI эффективно выгрузить вашего поставщика. Для выгрузки поставщика WMI требуется время от интервала, указанного в параметрах управления кэшем, до удвоенного интервала.

WMI выгружает поставщика одним из следующих способов:

  • Выгрузите поставщика после того, как он выполнит порученные ему задачи.
  • Быстро выгрузите всех поставщиков при завершении работы системы. Обратите внимание, что WMI выгружает поставщиков в процессе при завершении работы службы WMI из командной строки.

Хотя первый сценарий более распространен, необходимо написать поставщика для обеих возможностей.

В этом разделе рассматриваются следующие разделы:

Выгрузка неактивного поставщика

WMI выполняет следующие действия при выгрузке неактивного поставщика:

  • Определяет, неактивен ли поставщик.

    WMI использует свойство ClearAfter для определения времени простоя поставщика перед выгрузкой этого поставщика. Дополнительные сведения см. в разделе доступ ко времени простоя поставщика.

  • Вызывает метод у поставщика.

    Если поставщик был чистым поставщиком, то релиз полностью удаляет поставщика из активной памяти. Тем не менее, неполный поставщик может продолжать работать после вызовов WMI Release.

Доступ к времени простоя поставщика

Минимальное время, когда поставщик остается активным, определяется свойством ClearAfter. ClearAfter можно найти в экземплярах классов, производных от системного класса WMI __CacheControl в пространстве имен \root.

В следующем списке описываются классы, производные от __CacheControl, которые определяют выгрузку поставщика:

Можно изменить минимальное время, которое WMI позволяет поставщику оставаться неактивным, изменив свойство ClearAfter в экземпляре элемента управления кэшем для определенного типа поставщика. Например, чтобы ограничить время, когда поставщик свойств может оставаться неактивным, можно изменить свойство ClearAfter экземпляра __PropertyProviderCacheControl в пространстве имен oot \r.

Выгрузка поставщика, который также является клиентом WMI

Поставщику может потребоваться остаться как клиентом WMI после завершения выполнения функций, которые ему было поручено выполнить. Например, поставщик push-уведомлений может потребовать выдачи запросов к WMI. Дополнительные сведения см. в о том, как определить статус отправки или получения. В этом случае свойство Pure экземпляра __Win32Provider, представляющего поставщика, должно быть установлено в TRUE. Если для свойства Pure задано значение FALSE, поставщик готовится к выгрузке, вызывая IUnknown::Release для всех активных точек интерфейса, когда WMI вызывает метод Release своего основного интерфейса. Дополнительные сведения см. в разделе "Примечания" в __Win32Provider.

В следующей процедуре описывается, как реализовать метод освобождения ресурсов для основного интерфейса вашего поставщика.

Выгрузить поставщика

  1. Отпустите все указатели интерфейса, удерживаемые для WMI, когда WMI вызывает метод Release основного интерфейса вашего поставщика.

    Как правило, поставщик хранит указатели на интерфейсы IWbemServices и IWbemContext, предоставленные в IWbemProviderInit::Initialize.

  2. Если свойство Pure в связанном экземпляре __Win32Provider имеет значение FALSE, поставщик может перейти к роли клиентского приложения после вызова WMI release. Однако WMI не может разгрузить поставщика, работающего в качестве клиентской системы, что увеличивает нагрузку на систему.

    Поставщик с Pure установлен в 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. Дополнительные сведения см. в статье базы знаний Майкрософт Q148791 "Как предоставить собственную библиотеку DllMain в обычной библиотеке DLL MFC." (Этот ресурс может быть недоступен в некоторых языках и странах или регионах.)

В качестве альтернативы можно поместить код очистки в деструктор глобального класса. Дополнительные сведения см. в разделе "Выгрузка поставщика". Операционная система Windows не выделяет глобальные объекты в куче. Операционная система вызывает деструкторы при выгрузке DLL.

Ниже приведена простая процедура очистки, которая может быть включена в глобальный объект для WMI.

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

Существует множество ограничений на то, что можно сделать в коде очистки с использованием любого из подходов. Например, ни потоки, ни библиотеки DLL, которые не связаны неявным образом, не могут быть доступны каким-либо образом. Кроме того, при каких-либо обстоятельствах вы не можете выполнять вызовы COM.

Установка дескрипторов безопасности пространства имен

Обеспечение безопасности вашего поставщика

Разработка поставщика для WMI