1. 程式人生 > >C++通過WMI獲取計算機電池電壓的程式以及我出現的問題解決

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中的電壓值有一點差異