Change Brightness using WMI

做~自己de王妃 提交于 2019-12-11 06:44:40

问题


I have tried this Windows example Getting WMI Data from a Remote Computer and this other Calling a Provider Method, and both work correctly in my computer. However I have tried to use WMI to change the brightness and I am getting an error on step 6, in this part:

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

pEnum is a negative value.

IMPORTANT: While I was writing this question, I tried with different computers and I get errors in all of them, except when I use a laptop. Therefore, how can I change the brightness of a monitor?

I also realize that if I go to wbemtest.exe, in all my computers the class WmiMonitorBrightnessMethods and the method WmiSetBrightness exist, but only in the laptop there is an instance of it. In fact, in the computers when I click on view objects of the class I get this message (see image)

This is my code:

#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 --------------------------

    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\wminamespace
    // 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 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.
    }

    // Step 6: --------------------------------------------------
    // Call WmiSetBrightness method -----------------------------

    // set up to call the Win32_Process::Create method
    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  
    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);

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

    hres = pSvc->ExecMethod(pathVariable.bstrVal,
        MethodName,
        0,
        NULL,
        pClassInstance,
        NULL,
        NULL);
    VariantClear(&pathVariable);


    return 0;
}

回答1:


As Amit Shakya has stated. changing the brightness throught WMI is only possible in systems that can dynamically set the brightness (laptops and some some all-in-one devices).

However, there is a Microsoft function that allows you to change the brightness of an external monitor, SetMonitorBrightness.

See Microsoft library

I attach a simple example of how to do it:

// Includes
#include "PhysicalMonitorEnumerationAPI.h"
#include "HighLevelMonitorConfigurationAPI.h"

(...)

// Prepare variables
HMONITOR hMonitor = NULL;
HMONITOR hMonitorTest = NULL;
DWORD cPhysicalMonitors;
LPPHYSICAL_MONITOR pPhysicalMonitors = NULL;

// Get the screen
HWND hWnd = GetDesktopWindow();
hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);

_BOOL success = GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors);
if(success)
{
    pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));        
    if(pPhysicalMonitors != NULL)
    {
        success = GetPhysicalMonitorsFromHMONITOR(hMonitor,cPhysicalMonitors, pPhysicalMonitors);
        HANDLE hPhysicalMonitor = pPhysicalMonitors[0].hPhysicalMonitor;

        // Set brightness to 50%
        DWORD dwNewBrightness = 50;
        success = SetMonitorBrightness(hPhysicalMonitor, dwNewBrightness);

        // Free resources
        free(pPhysicalMonitors);
    }
}



回答2:


It is mostly because your PC does not support brightness controls via a software. For example in laptops there are hotkeys that can be used to control the brightness, if that exists that you will get an instance and make use of it via WMI.

To be sure, you can run below mentioned command in powershell. If it returns Not supported then you can not use WMI for these controls.

Get-CimInstance -Namespace root/WMI -ClassName WmiMonitorBrightnessMethods

Note : Hotkeys work via another softwares like Mobility Center etc.



来源:https://stackoverflow.com/questions/47333195/change-brightness-using-wmi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!