Я разрабатываю новый поставщик экземпляров WMI, и у меня возникли некоторые проблемы. Я могу успешно зарегистрировать своего провайдера, используя regsvr32.exe
. Приложение regsvr32
вызывает мою реализацию DllRegisterServer
и создает следующие ключи и значения реестра:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F} : (default) = "WMI Provider"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\InprocServer32 : (default) = "C:\MyWmiProvider.dll"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\InprocServer32 : ThreadingModel = Neutral
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\Version : (default) = 1.0.0
(Где {00000001-0000-0000-0000-00000000000F}
— это просто идентификатор тестового класса (CLSID))
Я также могу успешно добавить определения классов WMI, определенные в моем файле Mуправляемого Object Fформата (MOF), используя mofcomp.exe
. Я могу убедиться, что мои определения присутствуют в репозитории WMI, выполнив следующую команду:
Get-CimClass -Namespace "root/MyNamespace" | Where-Object CimClassName -like "MyClass_*"
Вот пример того, как выглядит мой файл MOF:
#pragma namespace("\\\\.\\root\\MyNamespace")
#pragma autorecover
instance of __Win32Provider as $P
{
Name = "MyWmiProvider";
ClsId = "{00000001-0000-0000-0000-00000000000F}";
};
instance of __InstanceProviderRegistration
{
Provider = $P;
SupportsGet = FALSE;
SupportsPut = FALSE;
SupportsDelete = FALSE;
SupportsEnumeration = TRUE;
};
[dynamic, provider("MyWmiProvider")]
class MyClass_ExampleName
{
[key]
uint14 Id;
[PropertyContext("Name")]
String Name;
};
Теперь, если я запущу следующее:
Get-CimInstance -Namespace "root/MyNamespace" -Class "MyClass_ExampleName"
Это приводит к следующей ошибке в PowerShell:
Get-CimInstance : Provider load failure
At line:1 char:1
+ Get-CimInstance -Namespace "root/MyNamespace" -Class "MyClass_ExampleName"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (root/Surface:Device_Status:String) [Get-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041013,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
Аналогичным образом, при выполнении этой команды создаются три (3) журнала просмотра событий:
#P8#
#P9#
#P10#
(Показано, что WMI правильно нашел DLL)
Я получаю аналогичные результаты, если пытаюсь вызвать Get-WMIObject
, за исключением того, что во втором журнале просмотра событий указано, что "Операция" была "Start IWbemServices::ExecQuery - root\MyNamespace : MyClass_ExampleName".
Что именно Get-WMIObject
и Get-CimInstance
делают в фоновом режиме?
Я просмотрел источник для Get-WMIObject
[здесь] и, несмотря на простые 6 строк, поиск соответствующих классов и вызовов функций не дает подробной информации. Мой интерфейс DLL включает только четыре (4) экспортируемых функции: DllGetClassObject()
, DllCanUnloadNow()
, DllRegisterServer()
и DllUnregisterServer()
. Я думал, что и Get-WMIObject
, и Get-CimInstance
сначала сделали вызов DllGetClassObject()
, чтобы получить фабрику классов WMI, но если я вызову функцию для сохранения строки во временный файл внутри DllGetClassObject()
, я замечаю, что при вызове этих команд PowerShell временный файл не создается.
Я стал еще более конкретным, создав новый проект после этот ответ чтобы я мог вызвать следующее:
DEFINE_GUID(InstanceProviderClassID, 0x00000001, 0x00000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F);
IWbemServices * pLoc = NULL;
CoCreateInstance(InstanceProviderClassID, NULL, CLSCTX_INPROC_SERVER, IID_IWbemServices, (LPVOID *)&pLoc);
Вызов CoCreateInstance()
в этом случае был успешен. Я даже заметил, что был создан временный файл журнала, указывающий, что DllGetClassObject()
на самом деле был вызван!
Даже если я возьму поставщика рабочего экземпляра, который у меня есть, и помещу тот же оператор печати (или аналогичный вызов для создания ключа/значения реестра) в его DllGetClassObject()
, ничего не сохраняется, чтобы указать, что эта функция вызывается при вызове этих команд PowerShell.
<сильный>1. Что мне здесь не хватает?
2. Почему DllGetClassObject()
никогда не вызывалась при выполнении Get-WMIObject
и Get-CimInstance
?
3. Почему я могу выполнить CoCreateInstance()
успешно, демонстрируя, что мой провайдер написан правильно, но получаю "сбой загрузки провайдера" при выполнении одного команд PowerShell?
(Примечание: для упрощения я обозначил все сервисные функции с WBEM_E_NOT_SUPPORTED
. Когда это делается в рабочем экземпляре провайдера, я по-прежнему вижу не "сбой загрузки провайдера", а скорее "не поддерживается .")
Get-CimInstance
с параметром-Debug
? Возможно, вы получите больше информации о том, что происходит. Кроме этого, попробуйте выполнить запрос с помощью инструментаwbemtest.exe
(в System32\wbem). stackoverflow.com/a/15070084/934946 - person Sage Pourpre   schedule 05.07.2020