Qt/C++调用windows Api库通过wmi的方式查询电脑能获取更多详细信息,也更加合理有技术性。
建议使用MSCV编译器,如MSCV 2017 ,Qt版本 : 5.13.1
目录导读
关于 WMI
关于 WMI:
Windows Management Instrumentation (WMI) 是 Microsoft 对基于 Web 的企业管理 (WBEM) 的实现,WBEM 是一项业界倡议,用于为访问企业环境中的管理信息开发一项标准技术。 WMI 使用通用信息模型 (CIM) 行业标准来表示系统、应用程序、网络、设备和其他托管组件
示例:创建 WMI 应用程序
创建 WMI 应用程序
官方代码示例:后续调用基本参照这种格式,值得注意的是需要把COINIT_MULTITHREADED 改为:COINIT_APARTMENTTHREADED
参考详见:
Qt中使用WMI时遇到的那些坑
示例:从本地计算机获取 WMI 数据
CIMWin32 WMI 提供程序-计算机系统硬件类
示例:打印Wmi执行的查询项的所有属性
通过获取第一条数据的属性字段名称,打印输出所有属性:
头文件引用项:
#include <iostream>
#include <comdef.h>
#include <WbemIdl.h>
#include <comutil.h>
#include <Windows.h>
#include <QStorageInfo>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "comsuppw.lib")
输出类型转换
QString check_vatiant_type(VARIANT Value,CIMTYPE _enum_type)
{
switch ( _enum_type ){
case CIM_ILLEGAL ://值: 0xfff非法值。
return QString::fromWCharArray(Value.bstrVal);
case CIM_EMPTY : //值: 0 空 (null) 值。
return "NULL";
case CIM_SINT8 : //值: 16//8 位有符号整数。
return QString::number(Value.iVal);
case CIM_SINT16 : //值: 2//16 位带符号整数。
return QString::number(Value.iVal);
case CIM_SINT32 : //值: 3//32 位带符号整数。
return QString::number(Value.intVal);
case CIM_SINT64 : //值: 20//64 位带符号整数。
return QString::number(Value.llVal,10);
case CIM_UINT8 : //值: 17//8 位无符号整数。
return QString::number(Value.uiVal);
case CIM_UINT16 : //值: 18//16 位无符号整数。
return QString::number(Value.uintVal);
case CIM_UINT32 : //值: 19//32 位无符号整数。
return QString::number(Value.uintVal);
case CIM_UINT64 : //值: 21//64 位无符号整数。
return QString::number(Value.ullVal,10);
case CIM_REAL32 : //值: 4//32 位实数。
return QString::number(Value.intVal);
case CIM_REAL64 : //值: 5//64 位实数。
return QString::number(Value.ullVal,10);
case CIM_BOOLEAN : //值: 11//一个布尔值。
return Value.boolVal?"TRUE":"FALSE";
case CIM_STRING : // 值: 8// 字符串值。
return QString::fromWCharArray(Value.bstrVal);
case CIM_DATETIME : //值: 101//一个日期时间值。
case CIM_REFERENCE : //值: 102//另一个对象的引用 (__Path) 。
case CIM_CHAR16 : //值: 103//16 位字符值。
case CIM_OBJECT : //值: 13//Object 值 。
case CIM_FLAG_ARRAY : // 值: 0x2000//数组值。
return QString::fromWCharArray(Value.bstrVal);
default:
return QString::fromWCharArray(Value.bstrVal);
}
}
执行查询
///输入 table_name /表名称 如: Win32_Refrigeration
void SelectWmi(QString table_name)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (FAILED(hres))
{
//Qt中使用WMI时遇到的那些坑儿
//https://blog.csdn.net/wangshubo1989/article/details/51869644
qDebug() << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return ; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
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 ((hres != RPC_E_TOO_LATE) && FAILED(hres))
{
qDebug() << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return ; // 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))
{
qDebug() << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return ; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
qDebug() << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return ; // Program has failed.
}
qDebug() << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on 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))
{
qDebug() << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return ; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(QString("SELECT * FROM "+table_name.trimmed()).toStdWString().c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
qDebug() << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return ; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
//IWbemClassObject 接口包含和操作类定义和类对象实例。
///属性字段列表
QList<BSTR> Headerlist;
///属性值 全部转换成字符串 用于显示到界面
QList<QStringList> Datas;
IWbemClassObject *pclsObj = NULL;
while (pEnumerator)
{
ULONG uReturn = 0;
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn || pclsObj == NULL)
{
break;
}
if(Headerlist.count()==0)
{
SAFEARRAY* pNames;
hres=pclsObj->GetNames(L"",WBEM_FLAG_ALWAYS,NULL,&pNames);
if (FAILED(hres))
{
qDebug()<<"获取属性名称失败!";
}
qDebug()<<"lLbound : "<<pNames->cDims;
qDebug()<<"cbElements : "<<pNames->cbElements;
BSTR HUGEP *pbstr;
// Get a pointer to the elements of the array.
hr = SafeArrayAccessData(pNames, (void HUGEP**)&pbstr);
if (FAILED(hr))
continue;
for (int i = 0; i < pNames->rgsabound->cElements; i++)
{
BSTR bstrTemp = pbstr[i];
Headerlist.append(bstrTemp);
}
SafeArrayDestroy(pNames);
}
if(Headerlist.count()==0)
continue;
QStringList _Data;
foreach (BSTR name , Headerlist) {
VARIANT vtProp;
CIMTYPE pType= CIM_EMPTY;
VariantInit(&vtProp);
hr = pclsObj->Get(name, 0, &vtProp, &pType, 0);
if(FAILED(hr))
{
_Data.append("ERROR");
}
else
_Data.append(check_vatiant_type(vtProp,pType));
VariantClear(&vtProp);
}
Datas.append(_Data);
pclsObj->Release();
}
emit SendTabValues(Headerlist,Datas);
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
}
通过Windows PowerShell 查询WMI 属性
在WMI 众多查询项中,如果需要预先简要查看相关属性,可以通过Windows PowerShell输入查询;
windows+ X 选择Windows PowerShell (管理员)查询:
以查询磁盘为例:
输入:Get-WmiObject -query "SELECT * FROM Win32_DiskDrive"
指定项查询:Get-WmiObject -query "SELECT name,Partitions,DeviceID,Model,Size,Caption,SystemName FROM WIN32_DiskDrive"
示例:通过WMI 查询电脑属性
查询磁盘 盘符信息:
代码:select DeviceID,DriveType,FreeSpace,Size,VolumeName,FileSystem from Win32_LogicalDisk
获取当前系统版本
代码:SELECT Caption,Name,OSArchitecture FROM Win32_OperatingSystem
获取主板型号
代码:SELECT Product From Win32_BaseBoard
获取CPU型号
代码:SELECT Name FROM Win32_Processor
获取显卡型号
代码:select Name from Win32_VideoController
获取内存大小
代码:SELECT TotalPhysicalMemory FROM Win32_ComputerSystem
获取电脑类型
代码:SELECT ChassisTypes FROM Win32_SystemEnclosure
获取硬盘型号
代码:SELECT Model From Win32_DiskDrive
示例源码
链接: https://pan.baidu.com/s/1QEGau1LQalW7HXv0E3kejA
提取码: 666v
双击查询电脑常用详细属性
编译器:MSCV2017 | QtCreator 5.13.1