Windows XP WMI - Monitoring Battery Charge Remaining

I have written a rountine based upon examples found online.  My intent is to detect the number of batteries in a portable WindowsXP computer and report the %Remaining of battery life for each battery.

My development laptop is a Dell Lattitude E6500 -- it has only one battery pack, yet when I run my routine it shows two batteries.

I run this WMI query:
SELECT * FROM CIM_Battery

and I get two results:
Win32_PortableBattery.DeviceID="Portable Battery 0"
Win32_Battery.DeviceID="43559Samsung SDIDELL MP4949A"

My routine iterates over this result set and finds that the SECOND "battery" has an estimated charge ("EstimatedChargeRemaining") of 83 (83%) -- this agrees with my Windows Power Meter -- this is the battery, the ONLY battery, I want to monitor.

My question is -- what is that FIRST battery result, the one named "Portable Battery 0" -- it doesn't report an EstimatedChargeRemaining.  My routine displays some impossible figure like 5156357% remaining.

I could choose to ignore this first battery by noticing that it has an impossible chargeremaining, but I'd rather understand WHAT it is.  I need this routine to work on other computers with 0, 1 or 2 batteries.  I want to be certain that I'm detecting real batteries, and ignoring things that are not real batteries...

Brian Withun



int __fastcall SPBatteryHealthData::GetChargeRemaining(TStringList *pResult)
{
    HRESULT hres;

    //***********************************************************************
    if (pResult==NULL) return -7; // caller MUST supply a valid list

    try { pResult->Clear(); } // clear the supplied list
    catch(...) { return -7; } // problem clearing list (invalid pointer?)

    //***********************************************************************
    try        { hres =  CoInitializeEx(0, COINIT_MULTITHREADED); } // Initialize COM.
    catch(...) { return -1;}

    if (FAILED(hres)) { return -1; } // Program has failed.

    //***********************************************************************
    // Initialize
    try { hres = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); }
    catch(...) { CoUninitialize();
                 return -2; } // failed to initialize security

    if (FAILED(hres)) { CoUninitialize();
                        return -2; } // failed to initialize security

    //***********************************************************************
    // Obtain the initial locator to Windows Management on a particular host computer
    IWbemLocator *pLoc = 0;
    try { hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc ); }
    catch(...) { CoUninitialize();
                 return -3; }        // failed to create IWbemLocator object

    if (FAILED(hres)) { CoUninitialize();
                        return -3; } // failed to create IWbemLocator object

    //***********************************************************************
    // Connect to the root\cimv2 namespace with the
    // current user and obtain pointer pSvc
    // to make IWbemServices calls.
    IWbemServices *pSvc = 0;
    try { // hres = pLoc->ConnectServer( WMINAMESPACE, NULL, NULL, 0, NULL, 0, 0, &pSvc );
             hres = pLoc->ConnectServer( L"ROOT\\CIMV2", NULL, NULL, 0, NULL, 0, 0, &pSvc ); }
    catch(...) { pLoc->Release();
                 CoUninitialize();
                 return -4; } // failed to connect

    if (FAILED(hres)) { pLoc->Release();
                        CoUninitialize();
                        return -4; } // failed to connect

    //***********************************************************************
    // Set the IWbemServices proxy so that impersonation of the user (client) occurs
    try { hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); }
    catch(...) { pSvc->Release();
                 pLoc->Release();
                 CoUninitialize();
                 return -5; } // failed. Could not set proxy blanket

    if (FAILED(hres)) { pSvc->Release();
                        pLoc->Release();
                        CoUninitialize();
                        return -5; } // failed. Could not set proxy blanket

    //***********************************************************************
    // Use the IWbemServices pointer to make requests of WMI.
    // For example, query for all the running processes

    ULONG uReturn = 0;
    IWbemClassObject *pclsObj;
    IEnumWbemClassObject* pEnumerator = NULL;

    try
    {
        hres = pSvc->ExecQuery( L"WQL", wqlQuery, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator );
    }
    catch(...) { pSvc->Release();
                 pLoc->Release();
                 CoUninitialize();
                 return -6; } // failed to execute the query

    if (FAILED(hres)) { pSvc->Release();
                        pLoc->Release();
                        CoUninitialize();
                        return -6; } // failed to execute the query

    //***********************************************************************
    VARIANT pvtProp;
    while (pEnumerator)
    {
        hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

        if (0==uReturn) break;

        hres = pclsObj->Get(L"EstimatedChargeRemaining", 0, &pvtProp, 0, 0);
        long lPercentCharge = pvtProp.lVal;

        hres = pclsObj->Get(L"DeviceId", 0, &pvtProp, 0, 0);
        AnsiString sID = pvtProp.bstrVal;

        // store the device id in the string list
        // store the corresponding percent charged (0..100) as a TObject* as its Object attribute
        int i = pResult->Add(sID);
        pResult->Objects[i] = (TObject*) lPercentCharge;
    }

    //***********************************************************************
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();

    return 0;
}

Open in new window

LVL 13
Brian WithunAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Lukasz ChmielewskiCommented:
try to iterate through other properties of the battery, this may be helpful with finding out what is the battery 0,

try systemname, statusinfo, etc.
the list of properties lies here:
http://msdn.microsoft.com/en-us/library/aa387189(VS.85).aspx
0
Brian WithunAuthor Commented:
Apparently I am querying the wrong class:

http://msdn.microsoft.com/en-us/library/aa387189(VS.85).aspx
"The CIM_Battery class represents the capabilities and management of the battery logical device. This class applies to batteries in laptop systems and other internal and external batteries."
http://msdn.microsoft.com/en-us/library/aa394074(VS.85).aspx
"The Win32_Battery class represents a battery connected to the computer system."
When I query with Win32_Battery rather than CIM_Battery, I only get the actual batteries.
So, say I have 2 batteries, one is bigger than the other.  How can I determine the entire system charge-level?  If the big battery is at 100% and the little battery is at 50%, then the system might be at a combined 82%.  How can that be determined ?
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Lukasz ChmielewskiCommented:
I'm afraid you cannot do this - what is the "entire system charge level" ? It is dependant rather on the big or the small battery ? The best thing to do would be to take mid value between those two.
0
Lukasz ChmielewskiCommented:
It would be grate if you would post the solution for the community. Thanks.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Scripting Languages

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.