我试图学习WMI是如何工作的,但是到目前为止,给出的默认示例非常糟糕。
下面是调用Win32_Process
类的Create
方法的示例:
https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--calling-a-provider-method
我已经添加了适当的错误处理,我们将每个调用的HRESULT存储在变量hres
中,并检查调用是否失败。
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
if (FAILED(hres))
{
wprintf("Failed to get class. Error code = 0x%lx\n", hres);
return hres;
}
代码一直正确执行到这里:
// Create the values for the in parameters
VARIANT varCommand;
varCommand.vt = VT_BSTR;
varCommand.bstrVal = _bstr_t(L"notepad.exe");
// Store the value for the in parameters
hres = pClassInstance->Put(L"CommandLine", 0,
&varCommand, 0);
wprintf(L"The command is: %s\n", V_BSTR(&varCommand));
pClassInstance->Put
抛出'ol c5的地方。
此时,对于SpawnInstance
的调用,hres
是S_OK
,但这些是我们为类示例提供的指针:
+pClass 0x000001c04e73fca0 IWbemClassObject *
- pClassInstance 0x000001c04e749d60 IWbemClassObject *
- IUnknown {...} IUnknown
- __vfptr 0x00007ff9f8d0ee98 {fastprox.dll!const CWbemInstance::`vftable'{for `_IWmiObject'}} {0x00007ff9f8c6f450 {fastprox.dll!CWbemObject::QueryInterface(void)}, ...} void * *
[0x00000000] 0x00007ff9f8c6f450 {fastprox.dll!CWbemObject::QueryInterface(void)} void *
[0x00000001] 0x00007ff9f8c907d0 {fastprox.dll!CWbemObject::AddRef(void)} void *
[0x00000002] 0x00007ff9f8c8ffd0 {fastprox.dll!CWbemObject::Release(void)} void *
+pInParamsDefinition 0x000001c04e743ca0 IWbemClassObject *
和varCommand
:
+varCommand BSTR = 0x000001c04e74ffe8 tagVARIANT
调用堆栈:
oleaut32.dll!SysAllocString()
vfbasics.dll!AVrfpSysAllocString()
wbemcomn.dll!CVar::SetVariant()
fastprox.dll!CWbemInstance::Put()
> Ele.exe!WMIConnection::InvokeMethod()
所以我认为bstrVal没有被正确设置?我尝试先用VariantInit
初始化它,然后尝试在堆上动态分配它,但都没有解决这个问题:
VARIANT varCommand;
VariantInit(&varCommand);
varCommand.vt = VT_BSTR;
varCommand.bstrVal = _bstr_t(L"notepad.exe");
我还尝试手动清零变量缓冲区,但没有效果。这是当访问冲突发生时,bstrVal
在内存转储中的结果:
bstrVal 0x000001c04e74ffe8 <Error reading characters of string.> wchar_t *
<Unable to read memory> wchar_t
2条答案
按热度按时间aiazj4mn1#
我想通了。网上有几个论坛帖子询问这个例子,没有给出解决方案,所以我现在很高兴提供这个。
Microsoft示例使用了不正确的类。
在Microsoft示例中,它们尝试调用
Win32_Process
类示例上的Put
方法来设置参数。这是不正确的。我们需要先获取
Win32_Process::Create
的类方法定义,然后在Win32_Process::Create
的一个 * 新示例 * 中设置它的参数。我们还需要构造
Win32_ProcessStartup
类对象的示例,因为它是Win32_Process::Create
的必需输入参数。在下面的示例中,我将填充
Win32_ProcessStartup
类示例的一个字段,您可以计算其余的字段。这段代码来自Microsoft示例:
变为(无可读性错误处理):
请注意,应检查所有这些
hres
返回是否失败。Win32_ProcessStartup
的定义如下:https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-processstartup
以及
Win32_Process
的Create
方法的定义:https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/create-method-in-class-win32-process
kokeuurv2#
这行代码创建了一个超出作用域的 * 临时 *
_bstr_t
对象,在将varCommand.bstrVal
赋值给varCommand.bstrVal
之后,该对象将销毁已分配的BSTR
内存。因此,当varCommand
传递给pClassInstance->Put()
时,varCommand.bstrVal
处于悬空状态,指向无效内存。这是 * 未定义的行为 *。请改用此命令来保持
BSTR
处于活动状态,直到您实际使用完它:否则,请改用
_variant_t
: