我正在开发一个新的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}
只是测试类ID(CLSID))
我还能够通过使用以下命令成功添加在 M 岁的 O 对象 F ormat(MOF)文件中定义的WMI类定义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)个事件查看器日志:
MyWmiProvider提供程序以结果代码0x80041013开始。 HostProcess = wmiprvse.exe; ProcessID = 2144; ProviderPath = C:\ MyWmiProvider.dll
Id = {FB6B3CF7-293E-0002-9316-73FB3E29D601}; ClientMachine = RTR-USERNAME;用户= MYDOMAIN \用户名; ClientProcessId = 19416;组件=未知;操作=启动IWbemServices :: CreateInstanceEnum-root \ MyNamespace:MyClass_ExampleName; ResultCode = 0x80041013;可能的原因=未知
MyWmiProvider提供程序以结果代码0x80041013开始。 HostProcess = wmiprvse.exe; ProcessID = 24636; ProviderPath = C:\ MyWmiProvider.dll
(表明WMI确实找到了DLL)
如果我尝试调用Get-WMIObject
,除了第二个事件查看器日志说“ Operation” 是“ Start IWbemServices :: ExecQuery-root \ MyNamespace之外,我会得到类似的结果: MyClass_ExampleName” 。
Get-WMIObject
和Get-CimInstance
在后台做什么?
我已经查找了Get-WMIObject
[here]的源代码,尽管仅用了6行,但是查找方面类和函数调用并没有产生详细的细节。我的DLL接口仅包括四(4)个导出函数:DllGetClassObject()
,DllCanUnloadNow()
,DllRegisterServer()
和DllUnregisterServer()
。我以为Get-WMIObject
和Get-CimInstance
都首先调用DllGetClassObject()
以获得WMI类工厂,但是如果我放置一个函数调用以将字符串保存到{ {3}},我在调用这些PowerShell命令时注意到没有创建临时文件。
通过在DllGetClassObject()
之后创建一个新项目,我变得更加具体,这样我就可以调用以下内容:
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);
在这种情况下,对this answer的呼叫成功。我什至还注意到临时日志文件已创建,表明实际上CoCreateInstance()
已被调用!
即使我采用自己拥有的工作实例提供程序,并将相同的打印语句(或类似的调用以创建注册表项/值)放入其DllGetClassObject()
函数中,也不会保存任何内容来表明这一点调用这些PowerShell命令时会调用该函数。
1。我在这里想念什么?
2.为什么在同时执行Get-WMIObject
和Get-CimInstance
时从未调用DllGetClassObject()
函数?
3.为什么我能够成功执行DllGetClassObject()
,说明我的提供程序编码正确,但是在执行其中一个PowerShell命令时却出现了“提供商加载失败” ? < / p>
(附带说明:为了使事情变得容易,我在WBEM_E_NOT_SUPPORTED
上标记了CoCreateInstance()
。在工作实例提供程序中完成此操作后,我仍然看不到“ provider加载失败” ,而是“不支持。” )