操作系统,CPU,内存,GPU
参考 C/C++获取操作系统、CPU、内存信息、硬盘、IP和MAC、进程信息(windows和linux)
显卡驱动
参考 【C++】WMI获取系统硬件信息(CPU/DISK/NetWork etc)
#include <iostream>
#include <string>
#include <string.h>
#include <winsock2.h> // include must before window.h
#include <iphlpapi.h>
#include <windows.h>
#include <DXGI.h>
#include <vector>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "DXGI.lib")
#pragma warning(disable: 4996) // avoid GetVersionEx to be warned
#define _WIN32_DCOM
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
// ***** global macros ***** //
static const int kMaxInfoBuffer = 256;
#define GBYTES 1073741824
#define MBYTES 1048576
#define KBYTES 1024
#define DKBYTES 1024.0
/*显卡驱动信息*/
void getDriver() {
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; // 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 (FAILED(hres))
{
cout << "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))
{
cout << "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))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return; // Program has failed.
}
//cout << "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))
{
cout << "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("SELECT * FROM Win32_VideoController"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "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* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
wcout << "VideoController Name:" << vtProp.bstrVal << endl;
hr = pclsObj->Get(L"DriverVersion", 0, &vtProp, 0, 0);
wcout << "VideoController DriverVersion:" << vtProp.bstrVal << endl;
VariantClear(&vtProp);
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
}
/*操作系统版本*/
void getOsInfo()
{
// get os name according to version number
OSVERSIONINFO osver = { sizeof(OSVERSIONINFO) };
GetVersionEx(&osver);
std::string os_name;
if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0)
os_name = "Windows 2000";
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)
os_name = "Windows XP";
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0)
os_name = "Windows 2003";
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)
os_name = "windows vista";
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1)
os_name = "windows 7";
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
os_name = "windows 10";
std::cout << "operating system: " << os_name << std::endl;
//dwMajorVersion 操作系统的主版本号,dwMinorVersion 操作系统的副版本号
//std::cout << "os version: " << osver.dwMajorVersion << '.' << osver.dwMinorVersion << std::endl;
}
#ifdef _WIN64
// method 2: usde winapi, works for x86 and x64
#include <intrin.h>
/*CPU*/
void getCpuInfo()
{
int cpuInfo[4] = { -1 };
char cpu_manufacture[32] = { 0 };
char cpu_type[32] = { 0 };
char cpu_freq[32] = { 0 };
__cpuid(cpuInfo, 0x80000002);
memcpy(cpu_manufacture, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000003);
memcpy(cpu_type, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000004);
memcpy(cpu_freq, cpuInfo, sizeof(cpuInfo));
//std::cout << "CPU manufacture: " << cpu_manufacture << std::endl;
//std::cout << "CPU type: " << cpu_type << std::endl;
//std::cout << "CPU main frequency: " << cpu_freq << std::endl;
std::cout << "CPU:" << cpu_manufacture << cpu_type << cpu_freq << std::endl;
}
#else
// mothed 1: this kind asm embedded in code only works in x86 build
// save 4 register variables
DWORD deax;
DWORD debx;
DWORD decx;
DWORD dedx;
// init cpu in assembly language
void initCpu(DWORD veax)
{
__asm
{
mov eax, veax
cpuid
mov deax, eax
mov debx, ebx
mov decx, ecx
mov dedx, edx
}
}
long getCpuFreq()
{
int start, over;
_asm
{
RDTSC
mov start, eax
}
Sleep(50);
_asm
{
RDTSC
mov over, eax
}
return (over - start) / 50000;
}
std::string getManufactureID()
{
char manuID[25];
memset(manuID, 0, sizeof(manuID));
initCpu(0);
memcpy(manuID + 0, &debx, 4); // copy to array
memcpy(manuID + 4, &dedx, 4);
memcpy(manuID + 8, &decx, 4);
return manuID;
}
std::string getCpuType()
{
const DWORD id = 0x80000002; // start 0x80000002 end to 0x80000004
char cpuType[49];
memset(cpuType, 0, sizeof(cpuType));
for (DWORD t = 0; t < 3; t++)
{
initCpu(id + t);
memcpy(cpuType + 16 * t + 0, &deax, 4);
memcpy(cpuType + 16 * t + 4, &debx, 4);
memcpy(cpuType + 16 * t + 8, &decx, 4);
memcpy(cpuType + 16 * t + 12, &dedx, 4);
}
return cpuType;
}
void getCpuInfo()
{
//std::cout << "CPU manufacture: " << getManufactureID() << std::endl;
//std::cout << "CPU type: " << getCpuType() << std::endl;
//std::cout << "CPU main frequency: " << getCpuFreq() << "MHz" << std::endl;
std::cout << "CPU :" << getManufactureID() << getCpuType() << getCpuFreq() << std::endl;
}
#endif
/*内存*/
void getMemoryInfo()
{
std::string memory_info;
MEMORYSTATUSEX statusex;
statusex.dwLength = sizeof(statusex);
if (GlobalMemoryStatusEx(&statusex))
{
unsigned long long total = 0, remain_total = 0, avl = 0, remain_avl = 0;
double decimal_total = 0, decimal_avl = 0;
remain_total = statusex.ullTotalPhys % GBYTES;
total = statusex.ullTotalPhys / GBYTES;
avl = statusex.ullAvailPhys / GBYTES;
remain_avl = statusex.ullAvailPhys % GBYTES;
if (remain_total > 0)
decimal_total = (remain_total / MBYTES) / DKBYTES;
if (remain_avl > 0)
decimal_avl = (remain_avl / MBYTES) / DKBYTES;
decimal_total += (double)total;
decimal_avl += (double)avl;
char buffer[kMaxInfoBuffer];
sprintf_s(buffer, kMaxInfoBuffer, "total %.2f GB (%.2f GB available)", decimal_total, decimal_avl);
memory_info.append(buffer);
}
std::cout << "Memory size:" << memory_info << std::endl;
}
// ---- get harddisk info ---- //
std::string execCmd(const char *cmd)
{
char buffer[128] = { 0 };
std::string result;
FILE *pipe = _popen(cmd, "r");
if (!pipe) throw std::runtime_error("_popen() failed!");
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
void getHardDiskInfo()
{
std::string hd_seiral = execCmd("wmic path win32_physicalmedia get SerialNumber");
std::cout << "HardDisk Serial Number: " << hd_seiral << std::endl;
}
// ---- get network info ---- //
void getNetworkInfo()
{
// PIP_ADAPTER_INFO struct contains network information
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
unsigned long adapter_size = sizeof(IP_ADAPTER_INFO);
int ret = GetAdaptersInfo(pIpAdapterInfo, &adapter_size);
if (ret == ERROR_BUFFER_OVERFLOW)
{
// overflow, use the output size to recreate the handler
delete pIpAdapterInfo;
pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[adapter_size];
ret = GetAdaptersInfo(pIpAdapterInfo, &adapter_size);
}
if (ret == ERROR_SUCCESS)
{
int card_index = 0;
// may have many cards, it saved in linklist
while (pIpAdapterInfo)
{
std::cout << "---- " << "NetworkCard " << ++card_index << " ----" << std::endl;
std::cout << "Network Card Name: " << pIpAdapterInfo->AdapterName << std::endl;
std::cout << "Network Card Description: " << pIpAdapterInfo->Description << std::endl;
// get IP, one card may have many IPs
PIP_ADDR_STRING pIpAddr = &(pIpAdapterInfo->IpAddressList);
while (pIpAddr)
{
char local_ip[128] = { 0 };
strcpy(local_ip, pIpAddr->IpAddress.String);
std::cout << "Local IP: " << local_ip << std::endl;
pIpAddr = pIpAddr->Next;
}
char local_mac[128] = { 0 };
int char_index = 0;
for (int i = 0; i < pIpAdapterInfo->AddressLength; i++)
{
char temp_str[10] = { 0 };
sprintf(temp_str, "%02X-", pIpAdapterInfo->Address[i]); // X for uppercase, x for lowercase
strcpy(local_mac + char_index, temp_str);
char_index += 3;
}
local_mac[17] = '\0'; // remove tail '-'
std::cout << "Local Mac: " << local_mac << std::endl;
// here just need the first card info
break;
// iterate next
//pIpAdapterInfo = pIpAdapterInfo->Next;
}
}
if (pIpAdapterInfo)
delete pIpAdapterInfo;
}
// ---- get process info ---- //
void getProcessInfo()
{
int pid = GetCurrentProcessId();
// TODO: cpu and mem usage
printf("Current Pid: %d\n", pid);
}
std::string WStringToString(const std::wstring &wstr)
{
std::string str(wstr.length(), ' ');
std::copy(wstr.begin(), wstr.end(), str.begin());
return str;
}
/*GPU*/
void getGPU() {
// 参数定义
IDXGIFactory * pFactory;
IDXGIAdapter * pAdapter;
std::vector <IDXGIAdapter*> vAdapters; // 显卡
// 显卡的数量
int iAdapterNum = 0;
// 创建一个DXGI工厂
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory));
if (FAILED(hr))
return;
// 枚举适配器
while (pFactory->EnumAdapters(iAdapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND)
{
vAdapters.push_back(pAdapter);
++iAdapterNum;
}
// 信息输出
//std::cout << "===============获取到" << iAdapterNum << "块显卡===============" << std::endl;
for (size_t i = 0; i < vAdapters.size(); i++)
{
//std::cout << "Video card" << i + 1 << ":" << std::endl;
// 获取信息
DXGI_ADAPTER_DESC adapterDesc;
vAdapters[i]->GetDesc(&adapterDesc);
std::wstring aa(adapterDesc.Description);
std::string bb = WStringToString(aa);
std::cout << "Video card " << i + 1 << " DedicatedVideoMemory:" << adapterDesc.DedicatedVideoMemory / 1024 / 1024 << "M" << std::endl;
std::cout << "Video card " << i + 1 << " SharedSystemMemory:" << adapterDesc.SharedSystemMemory / 1024 / 1024 << "M" << std::endl;
// 输出显卡信息
//std::cout << "系统视频内存:" << adapterDesc.DedicatedSystemMemory / 1024 / 1024 << "M" << std::endl;
//std::cout << "专用视频内存:" << adapterDesc.DedicatedVideoMemory / 1024 / 1024 << "M" << std::endl;
//std::cout << "共享系统内存:" << adapterDesc.SharedSystemMemory / 1024 / 1024 << "M" << std::endl;
//std::cout << "设备描述:" << bb.c_str() << std::endl;
//std::cout << "设备ID:" << adapterDesc.DeviceId << std::endl;
//std::cout << "PCI ID修正版本:" << adapterDesc.Revision << std::endl;
//std::cout << "子系统PIC ID:" << adapterDesc.SubSysId << std::endl;
//std::cout << "厂商编号:" << adapterDesc.VendorId << std::endl;
// 输出设备
IDXGIOutput * pOutput;
std::vector<IDXGIOutput*> vOutputs;
// 输出设备数量
int iOutputNum = 0;
while (vAdapters[i]->EnumOutputs(iOutputNum, &pOutput) != DXGI_ERROR_NOT_FOUND)
{
vOutputs.push_back(pOutput);
iOutputNum++;
}
//std::cout << std::endl;
//std::cout << "该显卡获取到" << iOutputNum << "个显示设备:" << std::endl;
for (size_t n = 0; n < vOutputs.size(); n++)
{
// 获取显示设备信息
DXGI_OUTPUT_DESC outputDesc;
vOutputs[n]->GetDesc(&outputDesc);
// 获取设备支持
UINT uModeNum = 0;
DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
UINT flags = DXGI_ENUM_MODES_INTERLACED;
vOutputs[n]->GetDisplayModeList(format, flags, &uModeNum, 0);
DXGI_MODE_DESC * pModeDescs = new DXGI_MODE_DESC[uModeNum];
vOutputs[n]->GetDisplayModeList(format, flags, &uModeNum, pModeDescs);
//std::cout << "DisplayDevice:" << n + 1 << " Name:" << outputDesc.DeviceName << std::endl;
std::cout << "DisplayDevice " << n + 1 << " Resolution ratio:" << outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left << "*" << outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top << std::endl;
// 所支持的分辨率信息
//std::cout << "分辨率信息:" << std::endl;
/*for (UINT m = 0; m < uModeNum; m++)
{
std::cout << "== 分辨率:" << pModeDescs[m].Width << "*" << pModeDescs[m].Height << " 刷新率" << (pModeDescs[m].RefreshRate.Numerator) / (pModeDescs[m].RefreshRate.Denominator) << std::endl;
}*/
}
vOutputs.clear();
}
vAdapters.clear();
}
int main(int argc, char *argv[])
{
//std::cout << "操作系统版本:" << std::endl;
getOsInfo();
//std::cout << "CPU:" << std::endl;
getCpuInfo();
//std::cout << "内存大小:" << std::endl;
getMemoryInfo();
//std::cout << "GPU:" << std::endl;
getGPU();
std::cout << "=== harddisk information ===" << std::endl;
getHardDiskInfo();
std::cout << "=== network information ===" << std::endl;
getNetworkInfo();
printf("=== process information ===\n");
getProcessInfo();
//std::cout << "显卡驱动:" << std::endl;
getDriver();
return 0;
}
electron获取电脑硬件信息,主线程调用c++程序,读取其输出的数据。
function runExec() {
// 执行命令行,如果命令不需要路径,或就是项目根目录,则不需要cwd参数:
let workerProcess = exec('sys.exe', {})
// 不受child_process默认的缓冲区大小的使用方法,没参数也要写上{}:workerProcess = exec(cmdStr, {})
// 打印正常的后台可执行程序输出
workerProcess.stdout.on('data', function(data) {
console.log('stdout: ' + data)
})
// 打印错误的后台可执行程序输出
workerProcess.stderr.on('data', function(data) {
console.log('stderr: ' + data)
})
// 退出之后的输出
workerProcess.on('close', function(code) {
console.log('out code:' + code)
})
}