0

The following code fails when ExecMethod is called. Can anyone pinpoint what I am doing wrong?

#define _WIN32_DCOM

#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>

# pragma comment(lib, "wbemuuid.lib")

int main(int iArgCnt, char ** argv)
{
    HRESULT hres;

    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
             << hex << hres << endl;
        return 1;                  // Program has failed.
    }

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you must specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM negotiates service
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );


    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" 
             << hex << hres << endl;
        CoUninitialize();
        return 1;                      // Program has failed.
    }

    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;

    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object. "
             << "Err code = 0x"
             << hex << hres << endl;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

    // Step 4: ---------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;

    // Connect to the local root\cimv2 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.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels for the proxy ------------------------

    hres = CoSetProxyBlanket(
        pSvc,                        // Indicates the proxy to set
        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
        NULL,                        // Server principal name 
        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL,                        // client identity
        EOAC_NONE                    // proxy capabilities 
    );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
             << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // set up to call the WmiSetBrightness Method
    BSTR MethodName = SysAllocString(L"WmiSetBrightness");
    BSTR ClassName = SysAllocString(L"WmiMonitorBrightnessMethods");

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

     V_VT(&var1) = VT_BSTR;
     V_BSTR(&var1) = SysAllocString(L"1000"); 
     hres = pClassInstance->Put(L"Timeout", 0, &var1, CIM_UINT32); //CIM_UINT64

     VARIANT var2;
     VariantInit(&var2);

     V_VT(&var2) = VT_BSTR;
     V_BSTR(&var2) = SysAllocString(L"30"); 
     hres = pClassInstance->Put(L"Brightness", 0, &var2, CIM_UINT8); 



    // Execute Method
    IWbemClassObject* pOutParams = NULL;
    hres = pSvc->ExecMethod(ClassName, MethodName, 0,
    NULL, pClassInstance, &pOutParams, NULL);



    if (FAILED(hres))
    {
        cout << "Could not execute method. Error code = 0x" 
             << hex << hres << endl;
        //VariantClear(&varCommand);
        SysFreeString(ClassName);
        SysFreeString(MethodName);
        pClass->Release();
        pInParamsDefinition->Release();
        pOutParams->Release();
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // To see what the method returned,
    // use the following code.  The return value will
    // be in &varReturnValue
    VARIANT varReturnValue;
    hres = pOutParams->Get(_bstr_t(L"ReturnValue"), 0, 
        &varReturnValue, NULL, 0);


    // Clean up
    //--------------------------
   // VariantClear(&varCommand);
    VariantClear(&varReturnValue);
    SysFreeString(ClassName);
    SysFreeString(MethodName);
    pClass->Release();
    pInParamsDefinition->Release();
    pOutParams->Release();
    pLoc->Release();
    pSvc->Release();
    CoUninitialize();
    return 0;
}
aCuria
  • 6,935
  • 14
  • 53
  • 89

2 Answers2

5

Since the question was tagged "C++" I tidied up your code by using C++ techniques for failure checking and cleanup. It turned out that you've forgotten to check for failure in several places. The code below reports first failure at GetObject(className, ...).

#define _WIN32_DCOM
#pragma comment(lib, "wbemuuid.lib")

#include <iostream>
#include <string>
#include <stdexcept>
#include <stdlib.h>     // EXIT_FAILURE, EXIT_SUCCESS
using namespace std;

#include <comdef.h>
#include <Wbemidl.h>
#define DEF_SMARTPTR_TYPE( Interface ) \
    _COM_SMARTPTR_TYPEDEF( Interface, __uuidof( Interface ) )

DEF_SMARTPTR_TYPE( IWbemLocator );
DEF_SMARTPTR_TYPE( IWbemServices );
DEF_SMARTPTR_TYPE( IWbemClassObject );

bool throwX( string const& s ) { throw std::runtime_error( s ); }

string hexFrom( unsigned long v )
{
    char    buf[40];
    sprintf( buf, "%08lx", v );
    return buf;
}

struct Fail
{
    string  message;
    explicit Fail( string const& aMessage ): message( aMessage ) {}
};

void operator ||( HRESULT hr, Fail const& failure )
{
    SUCCEEDED( hr )
        || throwX( failure.message + " (Error code 0x" + hexFrom( hr ) + ")" );
}

struct ComLibUsage
{
    struct Threading
    {
        enum Enum {
            singleThreaded  = COINIT_APARTMENTTHREADED,
            multiThreaded   = COINIT_MULTITHREADED
        };
    };

    ComLibUsage( Threading::Enum threading = Threading::multiThreaded )
    {
        ::CoInitializeEx( 0, threading )
            || Fail( "Failed to initialize COM library." );
    }

    ~ComLibUsage() { ::CoUninitialize(); }
};

void cppMain()
{
    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------
    ComLibUsage     comLibUsage( ComLibUsage::Threading::multiThreaded );

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you must specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------
    CoInitializeSecurity(
        NULL, 
        -1,                          // COM negotiates service
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        ) || Fail( "Failed to initialize security" );

    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------
    IWbemLocatorPtr     pLoc;
    CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc
        ) || Fail( "Failed to create IWbemLocator object." );

    // Step 4: ---------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method
    // Connect to the local root\cimv2 namespace
    // and obtain pointer pSvc to make IWbemServices calls.
    IWbemServicesPtr    pSvc;
    pLoc->ConnectServer(
        _bstr_t(L"ROOT\\wmi"), 
        NULL,
        NULL, 
        0, 
        NULL, 
        0, 
        0, 
        &pSvc
        ) || Fail( "Could not connect." );
    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels for the proxy ------------------------
    CoSetProxyBlanket(
        pSvc,                        // Indicates the proxy to set
        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
        NULL,                        // Server principal name 
        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL,                        // client identity
        EOAC_NONE                    // proxy capabilities 
        ) || Fail( "Could not set proxy blanket" );

    ////////////////////////////////////////////////////////////////
    // set up to call the WmiSetBrightness Method
    _bstr_t     methodName  = L"WmiSetBrightness";
    _bstr_t     className   = L"WmiMonitorBrightnessMethods";

    IWbemClassObjectPtr pClass;
    pSvc->GetObject(className, 0, NULL, &pClass, NULL)
        || Fail( "GetObject(className, ...) failed" );

    IWbemClassObjectPtr pInParamsDefinition;
    pClass->GetMethod(methodName, 0, &pInParamsDefinition, NULL)
        || Fail( "GetMethod(methodName, ...) failed" );

    IWbemClassObjectPtr pClassInstance;
    pInParamsDefinition->SpawnInstance(0, &pClassInstance)
        || Fail( "SpawnInstance failed" );

    _variant_t  var1( L"1000" );
    pClassInstance->Put(L"Timeout", 0, &var1, CIM_UINT32)   //CIM_UINT64
        || Fail( "Put failed for 'Timeout'" );

    _variant_t  var2( L"30" );
    pClassInstance->Put(L"Brightness", 0, &var2, CIM_UINT8)
        || Fail( "Put failed for 'Brightness'" );

    // Execute Method
    IWbemClassObject* pOutParams = NULL;
    //hres = pSvc->ExecMethod(className, methodName, 0,
    //NULL, pClassInstance, &pOutParams, NULL)
        //|| Fail( "Could not execute method" );

    // To see what the method returned,
    // use the following code.  The return value will
    // be in &varReturnValue
    _variant_t varReturnValue;
    pOutParams->Get(_bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0)
        || Fail( "Get failed" );
}

int main()
{
    try
    {
        cppMain();
        return EXIT_SUCCESS;
    }
    catch( exception const& x )
    {
        cerr << "!" << x.what() << endl;
    }
    return EXIT_FAILURE;
}

Cheers & hth. (even if it's a bit on the side of your question!),

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I ran the code you posted above, I dont get any failure at GetObject(className, ...). It fails for me at pOutParams->Get(_bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0) || Fail( "Get failed" ); – aCuria Oct 27 '10 at 09:08
  • 1
    I uncommented the code and I get a the following printed to stdout Connected to ROOT\CIMV2 WMI namespace !Could not execute method (Error code 0x8004102f) Press any key to continue . . . – aCuria Oct 27 '10 at 09:11
  • @aCuria: huh, if it fails at GetObject then it shouldn't get to the execute method part? Anyway, the HRESULT code is probably an internal one for WMI. If you know about a module that defines those HRESULT values then you can load that module in `errlook` utility and get some explanatory text. But probably all it says is that parameter is wrong or something like that. Possibly the params need to be provided in some other way? – Cheers and hth. - Alf Oct 27 '10 at 09:18
  • It doesnt fail at GetObject for me. I checked out the error code that ExecMethod was returning and I got WBEM_E_INVALID_METHOD_PARAMETERS 0x8004102F – aCuria Oct 27 '10 at 09:59
  • @aCuria: as I recall from glancing at the MSDN Lib documentation, the third argument (where you supply 0) seemed to be used to pass arguments. Cheers & hth., – Cheers and hth. - Alf Oct 27 '10 at 10:22
  • According to this msdn.microsoft.com/en-us/library/aa392103(VS.85).aspx the third param determines if it is a synchronous call. – aCuria Oct 30 '10 at 18:57
  • I like the way you wrote the error checking here. It makes it very easy to use and very readable. – T.Coutlakis Oct 18 '13 at 13:02
  • Code doesn't work. fails on ExecMethod with 0x8004102f – HardCoder Jun 19 '14 at 20:44
  • @HardCoder: the code is equivalent to the OP's code except that it has error checking. it's known to not work. the point is to inform you about the fact that it doesn't work at first opportunity, which you evidently managed to test, but then downvoted when you *failed to understand it*. i can only suggest 2 things: (1) use your real name on the net, and (2) don't downvote what you don't understand. – Cheers and hth. - Alf Jun 19 '14 at 22:33
  • ExecMethod Creates a Checkpoint for me but the outParam is still NULL, I need it to create Reference Point. @Cheersandhth.-Alf – CocoCrisp Apr 12 '18 at 11:48
  • @MilindW: I get a failure of the `ExecMethod` call when I remove the out-commenting of it. I don't know why, but all that was asked for was to pinpoint the location of failure: that's it. I checked now that the very short equivalent Powershell code [in Microsoft's documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/aa394549(v=vs.85).aspx) actually works. – Cheers and hth. - Alf Apr 12 '18 at 13:42
  • The HRESULT is `WBEM_E_INVALID_METHOD_PARAMETERS` according to [Microsoft's list](https://msdn.microsoft.com/en-us/library/aa394559(v=vs.85).aspx). – Cheers and hth. - Alf Apr 12 '18 at 13:50
  • I got my Job to Complete, If you need the detailed question it's here: https://stackoverflow.com/questions/49776105/wmi-execmethod-out-parameter-resultingsnapshot-is-null-irrespective-of-the-r @Cheersandhth.-Alf – CocoCrisp Apr 13 '18 at 06:10
0

Instead of the Step 4 & 6 from Example: Calling a Provider Method, it can set the brightness ABSOLUTELY.

Step 4:

        IWbemServices *pSvc = NULL;

        // Connect to the local root\cimv2 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.
        }

        cout << "Connected to ROOT\\WMI WMI namespace" << endl;

Step 6:

        BSTR ClassName = SysAllocString(L"WmiMonitorBrightnessMethods");
        BSTR MethodName = SysAllocString(L"WmiSetBrightness");
        BSTR bstrQuery = SysAllocString(L"Select * from WmiMonitorBrightnessMethods");
        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, //No of objects 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"Timeout");

        V_VT(&var1) = VT_BSTR;
        V_BSTR(&var1) = SysAllocString(L"0");
        hres = pClassInstance->Put(ArgName0,
            0,
            &var1,
            CIM_UINT32); //CIM_UINT64  
        printf("\nPut ArgName0 returned 0x%x:", hres);
        VariantClear(&var1);

        VARIANT var;
        VariantInit(&var);
        BSTR ArgName1 = SysAllocString(L"Brightness");

        V_VT(&var2) = VT_BSTR;
        V_BSTR(&var2) = SysAllocString(L"80"); //Brightness value
        hres = pClassInstance->Put(ArgName1,
            0,
            &var2,
            CIM_UINT8);
        VariantClear(&var2);
        printf("\nPut ArgName1 returned 0x%x:", hres);

        // Call the method  
        VARIANT pathVariable;
        VariantInit(&pathVariable);

        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
        //--------------------------
        //VariantClear(&varCommand);
        //VariantClear(&varReturnValue);
        SysFreeString(ClassName);
        SysFreeString(MethodName);
        pClass->Release();
        pClassInstance->Release();
        pInParamsDefinition->Release();
        //pOutParams->Release();
        pLoc->Release();
        pSvc->Release();
        CoUninitialize();

        system("pause");
        return 0;

ref: 通过WMI的方式去设置LCD背光亮度 Author: Tody

Hughes
  • 121
  • 1
  • 11