C++通过WMI获取计算机电池电压的程序以及我出现的问题解决

C++通过WMI获取计算机电池电压的程序以及我出现的问题解决
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include “stdafx.h”
#include “DXGI.h”
#include “vector”
#include <atlstr.h>
#include
//#include
#pragma comment(lib,“DXGI.lib”)

#define _WIN32_DCOM
#include <comdef.h>
#include <wbemidl.h>
#include <math.h>
*# pragma comment(lib, “wbemuuid.lib”)

using namespace std;

int Vmem(CString AdapterDesc);
int Dedicated_BatteryStatus=0;

int _tmain(int argc, _TCHAR* argv[])
{
//printf("\n argc:%d",argc); argc=1
IDXGIAdapter * pAdapter;
std::vector <IDXGIAdapter*> vAdapters;
IDXGIFactory* pFactory = NULL;
DXGI_ADAPTER_DESC desc;

if(FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory) ,(void**)&pFactory))) //使用FAILED宏来对COM组件的返回值HRESULT进行判断,如果函数正常执行,则返回S_OK
{
	return 0;
}

for (UINT i = 0;pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND;++i )
{
	CString Description;
	pAdapter->GetDesc( &desc );  //类 类型的指针pAdapter访问类的成员GetDesc
	Description=(CString)desc.Description; 
	//printf_s(_T("11111111111"));
	Vmem(Description);
}
SYSTEM_POWER_STATUS sysPowerStatus;
GetSystemPowerStatus(&sysPowerStatus);
printf("\nPercentage of electricity:%d%%",(int)sysPowerStatus.BatteryLifePercent);
getchar();
//Sleep(1000);
return 0;

}
int Vmem(CString Description)
{
HRESULT hres;

// Initialize COM.
hres =  CoInitializeEx(0, COINIT_MULTITHREADED);   //CoInitializeEx是API函数,初始化COM库
if (FAILED(hres))       //使用FAILED宏来判断函数CoInitializeEx()函数的返回值。
{
    cout << ";;Failed to initialize COM library. " << "Error code = 0x" << hex << hres << endl;
    return 1;              // Program has failed.
}




// Initialize ,初始化
hres =  CoInitializeSecurity(     //注册安全性并设置进程的安全级别。
	NULL,        //COM生成允许任何人访问的SID
    -1,      // COM negotiates service ,COM来处理认证服务                  
    NULL,    // Authentication services,认证服务数组
    NULL,    // Reserved,保留
	
    RPC_C_AUTHN_LEVEL_DEFAULT,    // authentication,身份验证,代理的默认认证级别
    RPC_C_IMP_LEVEL_IMPERSONATE,  // Impersonation,代理的默认模拟级别
    NULL,             // Authentication info ,身份信息,认证信息
    EOAC_NONE,        // Additional capabilities,其他功能,客户端或者服务器的附加能力
    NULL              // Reserved,保留
    );
                  
if (FAILED(hres))//使用FAILED宏来判断函数CoInitializeSecurity()函数的返回值。
{
    cout << ";;Failed to initialize security. " << "Error code = 0x"  << hex << hres << endl;
    CoUninitialize();   //API函数,用来告诉 Windows以单线程的方式创建com对象
    return 1;          // Program has failed.安全初始化失败
}



// Obtain the initial locator to Windows Management,获得最初管理员的定位
// on a particular host computer,特定的主机上	
IWbemLocator*pLoc=NULL;        //?定位器
//CoCreateInstance初始化 IWbemLocator 接口
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); //用指定的类标识符CLSID_WbemLocator创建一个Com对象,用指定的类标识符创建一个未初始化的对象
if (FAILED(hres))  //使用FAILED宏来判断函数CoCreateInstance()函数的返回值。
{
    cout << ";;Failed to create IWbemLocator object. "<< "Error code = 0x"<< hex << hres << endl; //创建IWbemLocator失败
    CoUninitialize();
    return 1;       // Program has failed.创建IWbemLocator失败
}


IWbemServices *pSvc = NULL;    // ?用于连接WMI
// Connect to the root\cimv2 namespace with the,连接root\cimv2
// current user and obtain pointer pSvc,获取用户信息和pSvc指针
// to make IWbemServices calls. 定义IWbemServices
hres = pLoc->ConnectServer(         //获得指定计算机上root\cimv2命名空间上的IwbemService对象的指针,连接到WMI
    _bstr_t(L"ROOT\\CIMV2"), // WMI namespace
    NULL,                    // User name ,用户名
    NULL,                    // User password,密码
    0,                       // Locale,地域
    NULL,                    // Security flags,安全标识                
    0,                       // Authority  ,权威    
    0,                       // Context object,上下文对象
    &pSvc                    // IWbemServices proxy,指向IWbemServices代理的指针
    );                                  
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;

// Set the IWbemServices proxy so that impersonation,设置IWbemServices代理以便于模拟
// of the user (client) occurs.用户或者客人身份

//设置WMI连接的安全性级别
//
hres = CoSetProxyBlanket( //设置代理信息

   pSvc,                         // the proxy to set,设置代理
   RPC_C_AUTHN_WINNT,            // authentication service,身份认证
   RPC_C_AUTHZ_NONE,             // authorization service,授权
   NULL,                         // Server principal name,服务器名称
   RPC_C_AUTHN_LEVEL_CALL,       // authentication level,认证级别1
   RPC_C_IMP_LEVEL_IMPERSONATE,  // impersonation level,模拟级别1
   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.设置代理失败
}




// Use the IWbemServices pointer to make requests of WMI., 用这个指针对WMI提出请求
// Make requests here:

// For example, query for all the running processes ,查找所有正在运行的进程
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Battery"),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,&pEnumerator); //查询有效的电池信息
if (FAILED(hres))
{
    cout << ";;Query failed. "<< "Error code = 0x" << hex << hres << endl;
    pSvc->Release();
    pLoc->Release();     
    CoUninitialize();
    return 1;               // Program has failed.查询失败
}
else
{ 
	IWbemClassObject *pclsObj=NULL;
	ULONG uReturn = 0;
	

	while (pEnumerator)
	{
       
       hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);  //Next函数

        if((0 == uReturn)||(0 == pclsObj))
       // if(0 == uReturn)

        {
            break;
        }
        
		//获取字段的值
		VARIANT vtProp;
		VARIANT vtPropDesc;
		//VARIANT vtPropCap;
		VARIANT vtPropDesig;
		VARIANT vtPropChemi;
		VARIANT vtPropEstima;
		vtProp.bstrVal=0;
		vtPropDesc.bstrVal=0;
		vtPropDesig.bstrVal=0;

		pclsObj->Get(L"BatteryStatus",0,&vtProp,0,0);			
		printf("\n BatteryStatus:%d",vtProp.bVal);

	    pclsObj->Get(L"Description",0,&vtPropDesc, 0, 0);				
		printf("\n Description:%s",(CString)vtPropDesc.bstrVal);
		
		pclsObj->Get(L"DesignVoltage", 0, &vtPropDesig, 0, 0);	
		printf("\n DesignVoltage:%ls",vtPropDesig.bstrVal);

		pclsObj->Get(L"Availability",0,&vtPropChemi, 0, 0);
		printf("\n Availability:%d",vtPropChemi.bVal);
		pclsObj->Get(L"EstimatedRunTime",0,&vtPropEstima, 0, 0);
		printf("\n EstimatedRunTime:%d",vtPropEstima.bstrVal);

		VariantClear(&vtProp);
		VariantClear(&vtPropDesc);
		VariantClear(&vtPropDesig);
		VariantClear(&vtPropChemi);
		VariantClear(&vtPropEstima);

		pclsObj->Release();
		}   
}

// Cleanup
// ========释放资源
pSvc->Release();
pLoc->Release(); 

//pEnumerator->Release(); 
CoUninitialize();

//getchar();

return 0;   // Program successfully completed.

}

问题一:刚开始我不懂这个程序的意思,其实关于计算机电池的信息已经在wmi上面,现在只不过是要把信息从wmi上面读下来而已。
问题二:前面一长串的东西一个一个搜了但是还是不知道在说啥,其实那些都是连接wmi的准备工作。如初始化com库的函数CoInitializeEx这些的,这些网上的都很多,我就不多说了!
问题三:我的电压一直出不来正确的值,从命令行运行.exe文件,直接双击.exe文件和VS里运行程序得到的结果都不一样,没有一个是对的!我的程序的问题在于printf("\n DesignVoltage:%d",vtPropDesig.bstrVal);这一句话,后面的vtPropDesig.boolVal是wchar_t宽字符型的,但是我的输出是窄字符型的。解决方法把%d改成%ls就行了。如果还不一样的话可以看看你的vs是不是管理员权限运行的;检查你的属性里的字符集,最好改成多字符集;还有一点就是看看你的电脑的电池是否正常并且电脑如果在充电的时候电压和wmi中的电压值有一点差异

猜你喜欢

转载自blog.csdn.net/jbh_sunshine/article/details/84071849