WMI C++ IWbemServices 。 WBEM_E_INVALID_METHOD_PARAMETERS 的执行方法
WMI C++ IWbemServices . ExecMethod for WBEM_E_INVALID_METHOD_PARAMETERS
我用的是WMI的机制。通过dsdt.dsl的修改和MOF文件的制作,我用C#完成了自定义WMI功能。但是有一个问题,当我想使用 C++ - MFC 与 MOF 文件通信时。 当代码运行到 IWbemServices 时。 ExecMethod函数,显示错误信息:WBEM_E_INVALID_METHOD_PARAMETERS(0x8004102F). 我觉得原因出在输入参数:boolean上。。。希望大家多多指教!
非常感谢!
acpimof.mof:
class WMIEvent : __ExtrinsicEvent
{
};
[WMI,
Dynamic,
Provider("WmiProv"),
Locale("MS\0x409"),
Description("Acpi_Commands"),
guid("{ABBC0F6D-8EA1-11d1-00A0-C90629100000}")
]
class Acpi_Commands
{
[key, read]
string InstanceName;
[read] boolean Active;
[WmiMethodId(1),
Implemented,
read, write,
Description("setReadLight")]
void setReadLight([in, Description("Status")] boolean Status);
};
acpi.cpp:
复制 MSDN – 示例:调用提供程序方法 (https://msdn.microsoft.com/en-us/library/aa390421(v=vs.85).aspx)。 Step 1, 2, 3 & 5 与示例完全相同,因此我不显示代码。我修改了步骤 4 & 6.
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the local namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\WMI"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// set up to call the Win32_Process::Create method
BSTR ClassName = SysAllocString(L"Acpi_Commands");
BSTR MethodName = SysAllocString(L"setReadLight");
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
// Create the values for the in parameters
VARIANT varCommand;
varCommand.vt = VT_BOOL;
varCommand.boolVal = VARIANT_TRUE;
// Store the value for the in parameters
hres = pClassInstance->Put(L"Status", 0, &varCommand, CIM_BOOLEAN);
// Execute Method
IWbemClassObject* pOutParams = NULL;
hres = pSvc->ExecMethod(ClassName, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
//Get error message: WBEM_E_INVALID_METHOD_PARAMETERS(0x8004102f)
if (FAILED(hres))
{
cout << "Could not execute method. Error code = 0x" << hex << hres << endl;
// Clean up(don't show here)
return 1; // Program has failed.
}
// Clean up(don't show here)
system("pause");
return 0;
我自己找到了解决办法,分享给需要的人:)
问题出现在 IWbemServices::ExecMethod 的第一个参数中,它需要指定的 属性 值而不是简单的 class 名称。所以它需要一些设置来获得指定的 属性 值。(但是 "Example: Calling a Provider Method" 只为参数设置 class 名称并且它有效......我猜原因发生在命名空间中(原文:"ROOT\CIMV2" => 这是Windows的标准模型),我使用"ROOT\WMI"连接WMI,所以需要指定属性值。如果我错了,请指正!)
请修改上面acpi.cpp的第6步。
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
BSTR ClassName = SysAllocString(L"Acpi_Commands");
BSTR MethodName = SysAllocString(L"setReadLight");
BSTR bstrQuery = SysAllocString(L"Select * from Acpi_Commands");
//The IEnumWbemClassObject interface is used to enumerate Common Information Model (CIM) objects
//and is similar to a standard COM enumerator.
IEnumWbemClassObject *pEnum = NULL;
hres = pSvc->ExecQuery(_bstr_t(L"WQL"), //Query Language
bstrQuery, //Query to Execute
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, //Make a semi-synchronous call
NULL, //Context
&pEnum /*Enumeration Interface*/);
hres = WBEM_S_NO_ERROR;
ULONG ulReturned;
IWbemClassObject *pObj;
DWORD retVal = 0;
//Get the Next Object from the collection
hres = pEnum->Next(WBEM_INFINITE, //Timeout
1, //One of object requested
&pObj, //Returned Object
&ulReturned /*No of object returned*/);
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
VARIANT var1;
VariantInit(&var1);
BSTR ArgName0 = SysAllocString(L"Status");
V_VT(&var1) = VT_BOOL;
V_BOOL(&var1) = VARIANT_FALSE;
hres = pClassInstance->Put(ArgName0, 0, &var1, CIM_BOOLEAN);
printf("\nPut ArgName0 returned 0x%x:", hres);
VariantClear(&var1);
// Call the method
VARIANT pathVariable;
VariantInit(&pathVariable);
//The IWbemClassObject::Get method retrieves the specified property value, if it exists.
hres = pObj->Get(_bstr_t(L"__PATH"),
0,
&pathVariable,
NULL,
NULL);
printf("\npObj Get returned 0x%x:", hres);
hres = pSvc->ExecMethod(pathVariable.bstrVal,
MethodName,
0,
NULL,
pClassInstance,
NULL,
NULL);
VariantClear(&pathVariable);
printf("\nExecMethod returned 0x%x:", hres);
printf("Terminating normally\n");
// Clean up
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pClassInstance->Release();
pInParamsDefinition->Release();
pLoc->Release();
pSvc->Release();
CoUninitialize();
system("pause");
return 0;
我用的是WMI的机制。通过dsdt.dsl的修改和MOF文件的制作,我用C#完成了自定义WMI功能。但是有一个问题,当我想使用 C++ - MFC 与 MOF 文件通信时。 当代码运行到 IWbemServices 时。 ExecMethod函数,显示错误信息:WBEM_E_INVALID_METHOD_PARAMETERS(0x8004102F). 我觉得原因出在输入参数:boolean上。。。希望大家多多指教! 非常感谢!
acpimof.mof:
class WMIEvent : __ExtrinsicEvent
{
};
[WMI,
Dynamic,
Provider("WmiProv"),
Locale("MS\0x409"),
Description("Acpi_Commands"),
guid("{ABBC0F6D-8EA1-11d1-00A0-C90629100000}")
]
class Acpi_Commands
{
[key, read]
string InstanceName;
[read] boolean Active;
[WmiMethodId(1),
Implemented,
read, write,
Description("setReadLight")]
void setReadLight([in, Description("Status")] boolean Status);
};
acpi.cpp:
复制 MSDN – 示例:调用提供程序方法 (https://msdn.microsoft.com/en-us/library/aa390421(v=vs.85).aspx)。 Step 1, 2, 3 & 5 与示例完全相同,因此我不显示代码。我修改了步骤 4 & 6.
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the local namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\WMI"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// set up to call the Win32_Process::Create method
BSTR ClassName = SysAllocString(L"Acpi_Commands");
BSTR MethodName = SysAllocString(L"setReadLight");
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
// Create the values for the in parameters
VARIANT varCommand;
varCommand.vt = VT_BOOL;
varCommand.boolVal = VARIANT_TRUE;
// Store the value for the in parameters
hres = pClassInstance->Put(L"Status", 0, &varCommand, CIM_BOOLEAN);
// Execute Method
IWbemClassObject* pOutParams = NULL;
hres = pSvc->ExecMethod(ClassName, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
//Get error message: WBEM_E_INVALID_METHOD_PARAMETERS(0x8004102f)
if (FAILED(hres))
{
cout << "Could not execute method. Error code = 0x" << hex << hres << endl;
// Clean up(don't show here)
return 1; // Program has failed.
}
// Clean up(don't show here)
system("pause");
return 0;
我自己找到了解决办法,分享给需要的人:)
问题出现在 IWbemServices::ExecMethod 的第一个参数中,它需要指定的 属性 值而不是简单的 class 名称。所以它需要一些设置来获得指定的 属性 值。(但是 "Example: Calling a Provider Method" 只为参数设置 class 名称并且它有效......我猜原因发生在命名空间中(原文:"ROOT\CIMV2" => 这是Windows的标准模型),我使用"ROOT\WMI"连接WMI,所以需要指定属性值。如果我错了,请指正!)
请修改上面acpi.cpp的第6步。
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
BSTR ClassName = SysAllocString(L"Acpi_Commands");
BSTR MethodName = SysAllocString(L"setReadLight");
BSTR bstrQuery = SysAllocString(L"Select * from Acpi_Commands");
//The IEnumWbemClassObject interface is used to enumerate Common Information Model (CIM) objects
//and is similar to a standard COM enumerator.
IEnumWbemClassObject *pEnum = NULL;
hres = pSvc->ExecQuery(_bstr_t(L"WQL"), //Query Language
bstrQuery, //Query to Execute
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, //Make a semi-synchronous call
NULL, //Context
&pEnum /*Enumeration Interface*/);
hres = WBEM_S_NO_ERROR;
ULONG ulReturned;
IWbemClassObject *pObj;
DWORD retVal = 0;
//Get the Next Object from the collection
hres = pEnum->Next(WBEM_INFINITE, //Timeout
1, //One of object requested
&pObj, //Returned Object
&ulReturned /*No of object returned*/);
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
VARIANT var1;
VariantInit(&var1);
BSTR ArgName0 = SysAllocString(L"Status");
V_VT(&var1) = VT_BOOL;
V_BOOL(&var1) = VARIANT_FALSE;
hres = pClassInstance->Put(ArgName0, 0, &var1, CIM_BOOLEAN);
printf("\nPut ArgName0 returned 0x%x:", hres);
VariantClear(&var1);
// Call the method
VARIANT pathVariable;
VariantInit(&pathVariable);
//The IWbemClassObject::Get method retrieves the specified property value, if it exists.
hres = pObj->Get(_bstr_t(L"__PATH"),
0,
&pathVariable,
NULL,
NULL);
printf("\npObj Get returned 0x%x:", hres);
hres = pSvc->ExecMethod(pathVariable.bstrVal,
MethodName,
0,
NULL,
pClassInstance,
NULL,
NULL);
VariantClear(&pathVariable);
printf("\nExecMethod returned 0x%x:", hres);
printf("Terminating normally\n");
// Clean up
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pClassInstance->Release();
pInParamsDefinition->Release();
pLoc->Release();
pSvc->Release();
CoUninitialize();
system("pause");
return 0;