WMI C++ IWbemServices . ExecMethod для WBEM_E_INVALID_METHOD_PARAMETERS

Я использовал механизм WMI. Через модификацию dsdt.dsl и производство файла MOF, я выполняю пользовательскую функцию WMI C# . Но есть проблема, когда я хочу использовать C++ — MFC для связи с файлом MOF. Во время выполнения кода в IWbemServices . Функция ExecMethod, она показывает сообщение об ошибке: WBEM_E_INVALID_METHOD_PARAMETERS(0x8004102F). Я думаю, что причина происходит с входным параметром: boolean… надеюсь, каждый может предоставить некоторые предложения!
Большое спасибо!

acpimof.mof:

class WMIEvent : __ExtrinsicEvent
{
};

[WMI,
 Dynamic,
 Provider("WmiProv"),
 Locale("MSx409"),
 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.СРР:

Скопируйте пример MSDN: вызов метода поставщика ( https://msdn.microsoft.com/en-us/library/aa390421 (v=против 85).aspx). Шаг 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"ROOTWMI"),
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;

1 ответ

  1. Я нашел решение самостоятельно, и я делюсь этим для тех, кто нуждается:)

    Проблема возникает в первом параметре для IWbemServices:: ExecMethod, которому требуется указанное значение свойства, а не простое имя класса. Таким образом, для получения указанного значения свойства требуется некоторая настройка.(Но «пример: вызов метода поставщика» только задает имя класса для параметра, и это работает… Я предполагаю, что причина происходит в namesapce (оригинал: «ROOT\CIMV2» => это стандартная модель для Windows), и я использую «ROOT\WMI» для подключения к WMI, поэтому ему нужно указанное значение свойства. Если я ошибаюсь, пожалуйста, поправьте меня!)

    Пожалуйста, пересмотрите Шаг 6 acpi.cpp выше.

    // 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;