535 lines
17 KiB
C++
535 lines
17 KiB
C++
//
|
||
// Created by HW on 2023/07/27.
|
||
//
|
||
|
||
#include <QProcess>
|
||
#include <QScreen>
|
||
#include <QCryptographicHash>
|
||
#include <wbemidl.h>
|
||
#include "netio.h"
|
||
#include "config.h"
|
||
#include <cstdlib>
|
||
#include <ctime>
|
||
#include <QEventLoop>
|
||
#include <QTimer>
|
||
#include <cstring>
|
||
#include <QJsonArray>
|
||
#include <QSysInfo>
|
||
#include <QStorageInfo>
|
||
#include <comutil.h>
|
||
#include <iostream>
|
||
#include <QGuiApplication>
|
||
#include <ctime>
|
||
#pragma comment(lib, "wbemuuid.lib")
|
||
#ifdef _DEBUG
|
||
#pragma comment(lib, "Qt5Networkd.lib")
|
||
#else
|
||
#pragma comment(lib, "Qt5Network.lib")
|
||
#endif
|
||
#pragma comment(lib,"comsuppw.lib")
|
||
//读取注册表获取MachineUUID
|
||
inline QString getMachineGUID(){
|
||
HKEY hKey;
|
||
RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography",
|
||
0,KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||
DWORD dwType1 = REG_SZ;
|
||
DWORD dwLen = MAX_PATH;
|
||
WCHAR buf[100];
|
||
RegQueryValueExA(hKey, "MachineGuid" ,0 ,&dwType1, (LPBYTE)buf, &dwLen);
|
||
QString guid=QString::fromWCharArray(buf);
|
||
return guid;
|
||
}
|
||
|
||
RequestBodyBase::RequestBodyBase(){
|
||
wchar_t unix_time[65]={0};
|
||
wsprintf(unix_time,L"%ld",std::time(0));
|
||
QString request_id=QString::fromWCharArray(unix_time);
|
||
//打开配置文件
|
||
QFile *infFile=new QFile(".\\config\\information.cfg");
|
||
if(!infFile->open(QIODevice::ReadOnly|QIODevice::Text)){
|
||
QMessageBox::critical(nullptr,QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("无法打开配置文件"));
|
||
delete infFile;
|
||
exit(1);
|
||
}
|
||
//读取配置文件
|
||
QByteArray bytes;
|
||
bytes=infFile->readAll();
|
||
infFile->close();
|
||
delete infFile;
|
||
//转化为json
|
||
qJsonDocument=QJsonDocument::fromJson(bytes);
|
||
if(qJsonDocument.isObject()){
|
||
//读取数据,写入对应字段
|
||
QJsonObject obj_root=qJsonDocument.object();
|
||
if(obj_root.value("product")==QJsonValue::Undefined){
|
||
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
|
||
exit(1);
|
||
}
|
||
product=obj_root.value("product").toString();
|
||
if(obj_root.value("partner_id")==QJsonValue::Undefined){
|
||
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
|
||
exit(1);
|
||
}
|
||
partner_id=obj_root.value("partner_id").toString();
|
||
if(obj_root.value("release")==QJsonValue::Undefined){
|
||
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
|
||
exit(1);
|
||
}
|
||
release=obj_root.value("release").toString();
|
||
if(obj_root.value("version")==QJsonValue::Undefined){
|
||
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
|
||
exit(1);
|
||
}
|
||
version=obj_root.value("version").toString();
|
||
if(obj_root.value("device_id")==QJsonValue::Undefined){
|
||
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
|
||
exit(1);
|
||
}
|
||
device_id=obj_root.value("device_id").toString();
|
||
}else{
|
||
//处理错误
|
||
QMessageBox::warning(nullptr,"错误","配置文件损坏");
|
||
exit(1);
|
||
}
|
||
//获取操作系统版本
|
||
os="Windows";
|
||
OSVERSIONINFOEX os;
|
||
os.dwOSVersionInfoSize=sizeof(os);
|
||
GetVersionEx((OSVERSIONINFO *)&os);
|
||
switch(os.dwMajorVersion){//主版本号
|
||
case 5: //不兼容Windows 2000,因此5.x一定是Windows XP
|
||
os_version="Windows XP";
|
||
break;
|
||
case 6:
|
||
switch(os.dwMinorVersion){ //次版本号
|
||
case 0:
|
||
os_version="Windows Vista or Windows Server 2008";
|
||
break;
|
||
case 1:
|
||
os_version="Windows 7 or Windows Server 2008 R2";
|
||
break;
|
||
case 2:
|
||
os_version="Windows 8 or Windows Server 2012";
|
||
break;
|
||
case 3:
|
||
os_version="Windows 8.1 or Windows Server 2012 R2";
|
||
break;
|
||
default:
|
||
os_version="Unknown";
|
||
}
|
||
case 10: //这几个系统都是10.0
|
||
os_version="Windows 10, Windows 11, Windows Server 2016 or Windows Server 2019";
|
||
break;
|
||
default:
|
||
os_version="Unknown";
|
||
}
|
||
//如果device_id是空值
|
||
if(device_id.isEmpty()){
|
||
//读取MachineGUID并取MD5作为device_id
|
||
QByteArray hash = QCryptographicHash::hash(getMachineGUID().toUtf8(), QCryptographicHash::Md5);
|
||
device_id=hash.toHex();
|
||
infFile=new QFile(".\\config\\information.cfg");
|
||
if(!infFile->open(QIODevice::WriteOnly|QIODevice::Text)){
|
||
//处理错误
|
||
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("无法覆写配置文件"));
|
||
infFile->close();
|
||
delete infFile;
|
||
exit(1);
|
||
}
|
||
//加入json序列
|
||
QJsonValue value=device_id;
|
||
QJsonObject obj_root;
|
||
obj_root.insert("device_id",value);
|
||
qJsonDocument.setObject(obj_root);
|
||
//写入配置文件
|
||
infFile->write(qJsonDocument.toJson());
|
||
//关闭文件;
|
||
infFile->close();
|
||
delete infFile;
|
||
}
|
||
QJsonValue requestId_json=QJsonValue(request_id);
|
||
QJsonObject obj_root;
|
||
//插入request_id
|
||
obj_root.insert("request_id",requestId_json);
|
||
qJsonDocument.setObject(obj_root);
|
||
}
|
||
|
||
|
||
|
||
void ConfigRequest::sendRequest(ConfigResponse *configResponse) {
|
||
timer = new QTimer(this);
|
||
QNetworkAccessManager *httpMgr = new QNetworkAccessManager();
|
||
/* QFile *file=new QFile(".\\config\\config.cfg");
|
||
if(!file->open(QIODevice::ReadOnly|QIODevice::Text)){
|
||
QMessageBox::warning(nullptr,"错误","无法打开配置文件");
|
||
file->close();
|
||
delete file;
|
||
exit(1);
|
||
}*/
|
||
QNetworkRequest requestInfo;
|
||
//HTTP请求
|
||
//请求头
|
||
requestInfo.setUrl(QUrl(CONFIG_URL));
|
||
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
|
||
//保存响应的变量
|
||
reply = httpMgr->post(requestInfo,qJsonDocument.toJson());
|
||
//开启一个循环,直到超时或者获取到数据为止
|
||
connect(reply,&QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
|
||
//设置定时器防止超时
|
||
connect(timer,&QTimer::timeout,this,&ConfigRequest::cancelDownload);
|
||
timer->start(5000);
|
||
//启动循环
|
||
eventLoop.exec();
|
||
delete httpMgr;
|
||
QJsonDocument result;
|
||
configResponse=new ConfigResponse;
|
||
memset(configResponse,0,sizeof(*configResponse));
|
||
//如果没有错误
|
||
if(reply->error() == QNetworkReply::NoError) {
|
||
result = QJsonDocument::fromJson(reply->readAll());
|
||
}else{
|
||
//如果有错误
|
||
configResponse->succeed=false;
|
||
delete reply;
|
||
delete timer;
|
||
return;
|
||
}
|
||
//如果数据完整
|
||
if(result.isObject()){
|
||
QJsonObject obj_root=result.object();
|
||
QJsonArray array;
|
||
array = obj_root.value("menu").toArray();
|
||
configResponse->menus=new QList<Menu>;
|
||
auto i=0;
|
||
for(auto value:array){
|
||
QJsonObject object=value.toObject();
|
||
Menu menu;
|
||
menu.img=object.value("img").toString();
|
||
menu.img_cover=object.value("img_cover").toString();
|
||
menu.title=object.value("title").toString();
|
||
menu.func=object.value("func").toString();
|
||
menu.url=object.value("url").toString();
|
||
*configResponse->menus << menu;
|
||
i++;
|
||
}
|
||
}else{
|
||
//数据不完整
|
||
configResponse->succeed=false;
|
||
delete reply;
|
||
delete timer;
|
||
return;
|
||
}
|
||
}
|
||
void RequestBodyBase::cancelDownload() {
|
||
disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
|
||
eventLoop.quit();
|
||
reply->abort();
|
||
}
|
||
void RequestBodyBase::sendRequest() {
|
||
timer = new QTimer(this);
|
||
QNetworkAccessManager *httpMgr = new QNetworkAccessManager();
|
||
QNetworkRequest requestInfo;
|
||
//HTTP请求
|
||
//请求头
|
||
requestInfo.setUrl(QUrl(OP_URL));
|
||
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
|
||
//保存响应的变量
|
||
reply = httpMgr->post(requestInfo,qJsonDocument.toJson());
|
||
//开启一个循环,直到超时或者获取到数据为止
|
||
connect(reply,&QNetworkReply::finished, this, &RequestBodyBase::cancelDownload);
|
||
//设置定时器防止超时
|
||
connect(timer,&QTimer::timeout,&eventLoop,&QEventLoop::quit);
|
||
timer->start(5000);
|
||
//启动循环
|
||
eventLoop.exec();
|
||
delete timer;
|
||
delete httpMgr;
|
||
delete reply;
|
||
}
|
||
|
||
|
||
DeviceRequest::DeviceRequest() : RequestBodyBase() {
|
||
//CPU
|
||
QString cpu = QSysInfo::currentCpuArchitecture();
|
||
//内存大小
|
||
MEMORYSTATUSEX status;
|
||
status.dwLength = sizeof(status);
|
||
GlobalMemoryStatusEx(&status);
|
||
int ram = status.ullTotalPhys / 1024 / 1024;
|
||
//硬盘大小
|
||
QStorageInfo storage = QStorageInfo::root();
|
||
int disk = storage.bytesTotal() / static_cast<qulonglong>(1024 * 1024 * 1024);
|
||
//显卡型号
|
||
QStringList gpus;
|
||
BOOL success;
|
||
DWORD deviceIndex = 0;
|
||
DISPLAY_DEVICE displayDevice;
|
||
displayDevice.cb = sizeof(displayDevice);
|
||
while (EnumDisplayDevices(NULL, deviceIndex, &displayDevice, 0)) {
|
||
WCHAR valueName[128];
|
||
DWORD valueSize;
|
||
DWORD valueType;
|
||
BYTE valueData[MAX_PATH];
|
||
HKEY hKey;
|
||
WCHAR keyName[128];
|
||
wsprintf(keyName, L"SYSTEM\\CurrentControlSet\\Control\\Video\\%s\\HardwareInformation",
|
||
displayDevice.DeviceID);
|
||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||
valueSize = sizeof(valueData);
|
||
wsprintf(valueName, L"HardwareInformation.AdapterString");
|
||
if (RegQueryValueEx(hKey, valueName, NULL, &valueType, valueData, &valueSize) == ERROR_SUCCESS) {
|
||
Q_ASSERT(valueType == REG_SZ);
|
||
QString adapterString = QString::fromWCharArray((wchar_t *) valueData, valueSize / sizeof(wchar_t) - 1);
|
||
gpus.append(adapterString);
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
deviceIndex++;
|
||
displayDevice.cb = sizeof(displayDevice);
|
||
}
|
||
//主板型号
|
||
QString motherboard = QSysInfo::prettyProductName();
|
||
//WMI获取网卡型号
|
||
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to initialize COM library." << std::endl;
|
||
return;
|
||
}
|
||
QStringList netCards;
|
||
hr = CoInitializeSecurity(
|
||
NULL,
|
||
-1,
|
||
NULL,
|
||
NULL,
|
||
RPC_C_AUTHN_LEVEL_DEFAULT,
|
||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||
NULL,
|
||
EOAC_NONE,
|
||
NULL
|
||
);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to initialize security." << std::endl;
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
|
||
IWbemLocator* pLoc = NULL;
|
||
hr = CoCreateInstance(
|
||
CLSID_WbemLocator,
|
||
NULL,
|
||
CLSCTX_INPROC_SERVER,
|
||
IID_IWbemLocator,
|
||
(LPVOID*)&pLoc
|
||
);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to create IWbemLocator object." << std::endl;
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
|
||
IWbemServices* pSvc = NULL;
|
||
hr = pLoc->ConnectServer(
|
||
_bstr_t(L"ROOT\\CIMV2"),
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
0,
|
||
0,
|
||
&pSvc
|
||
);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to connect to WMI service." << std::endl;
|
||
pLoc->Release();
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
|
||
hr = CoSetProxyBlanket(
|
||
pSvc,
|
||
RPC_C_AUTHN_WINNT,
|
||
RPC_C_AUTHZ_NONE,
|
||
NULL,
|
||
RPC_C_AUTHN_LEVEL_CALL,
|
||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||
NULL,
|
||
EOAC_NONE
|
||
);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to set security blanket." << std::endl;
|
||
pSvc->Release();
|
||
pLoc->Release();
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
|
||
IEnumWbemClassObject* pEnumerator = NULL;
|
||
hr = pSvc->ExecQuery(
|
||
_bstr_t("WQL"),
|
||
_bstr_t("SELECT * FROM Win32_NetworkAdapter WHERE PhysicalAdapter = TRUE AND NetConnectionStatus = 3"),
|
||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
||
NULL,
|
||
&pEnumerator
|
||
);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to execute WQL query for Win32_NetworkAdapter." << std::endl;
|
||
pSvc->Release();
|
||
pLoc->Release();
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
IWbemClassObject* pClassObj = NULL;
|
||
ULONG uReturn = 0;
|
||
while (pEnumerator) {
|
||
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &uReturn);
|
||
if (uReturn == 0) {
|
||
break;
|
||
}
|
||
|
||
VARIANT vtProp;
|
||
hr = pClassObj->Get(L"Caption", 0, &vtProp, 0, 0);
|
||
if (SUCCEEDED(hr)) {
|
||
QString str=QString::fromWCharArray(vtProp.bstrVal);
|
||
VariantClear(&vtProp);
|
||
netCards.append(str);
|
||
}
|
||
|
||
pClassObj->Release();
|
||
}
|
||
//WMI获取声卡型号
|
||
hr = pSvc->ExecQuery(
|
||
_bstr_t("WQL"),
|
||
_bstr_t("SELECT * FROM Win32_SoundDevice"),
|
||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
||
NULL,
|
||
&pEnumerator
|
||
);
|
||
if (FAILED(hr)) {
|
||
std::cerr << "Failed to execute WQL query for Win32_SoundDevice." << std::endl;
|
||
pSvc->Release();
|
||
pLoc->Release();
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
QStringList audioCards;
|
||
while (pEnumerator) {
|
||
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &uReturn);
|
||
if (uReturn == 0) {
|
||
break;
|
||
}
|
||
|
||
VARIANT vtProp;
|
||
hr = pClassObj->Get(L"Name", 0, &vtProp, 0, 0);
|
||
if (SUCCEEDED(hr)) {
|
||
QString str=QString::fromWCharArray(vtProp.bstrVal);
|
||
VariantClear(&vtProp);
|
||
audioCards.append(str);
|
||
}
|
||
|
||
pClassObj->Release();
|
||
}
|
||
hr = pSvc->ExecQuery(
|
||
bstr_t("WQL"),
|
||
bstr_t("SELECT * FROM Win32_PhysicalMemory"),
|
||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
||
NULL,
|
||
&pEnumerator
|
||
);
|
||
if (FAILED(hr))
|
||
{
|
||
std::cout << "Query failed. Error code: " << hr << std::endl;
|
||
pSvc->Release();
|
||
pLoc->Release();
|
||
CoUninitialize();
|
||
return;
|
||
}
|
||
QStringList RAMModel;
|
||
while (pEnumerator)
|
||
{
|
||
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &uReturn);
|
||
if (uReturn == 0)
|
||
{
|
||
break;
|
||
}
|
||
|
||
VARIANT vtProp;
|
||
hr = pClassObj->Get(L"Manufacturer", 0, &vtProp, 0, 0);
|
||
if (SUCCEEDED(hr))
|
||
{
|
||
std::wcout << "Manufacturer: " << vtProp.bstrVal << std::endl;
|
||
VariantClear(&vtProp);
|
||
}
|
||
|
||
hr = pClassObj->Get(L"PartNumber", 0, &vtProp, 0, 0);
|
||
if (SUCCEEDED(hr))
|
||
{
|
||
RAMModel.append(QString::fromWCharArray(vtProp.bstrVal));
|
||
VariantClear(&vtProp);
|
||
}
|
||
|
||
pClassObj->Release();
|
||
}
|
||
pSvc->Release();
|
||
pLoc->Release();
|
||
CoUninitialize();
|
||
DISPLAY_DEVICE d = { sizeof(DISPLAY_DEVICE) };
|
||
::EnumDisplayDevices(NULL, 0, &d, 0);
|
||
QString monitor=QString::fromWCharArray(d.DeviceString, wcslen(d.DeviceString));
|
||
//发送
|
||
//构造JSON
|
||
QJsonDocument *device=new QJsonDocument;
|
||
QJsonObject *object=new QJsonObject;
|
||
object->insert("CPU",QJsonValue(cpu));
|
||
object->insert("RAM",QJsonValue(ram));
|
||
object->insert("Hard_Disk",QJsonValue(disk));
|
||
QJsonArray *gpu_array=new QJsonArray;
|
||
for(auto gpu:gpus) {
|
||
gpu_array->append(gpu);
|
||
}
|
||
object->insert("GPU",*gpu_array);
|
||
delete gpu_array;
|
||
object->insert("Mother_Board",motherboard);
|
||
QJsonArray *RAMModel_json=new QJsonArray;
|
||
for(auto RAM:RAMModel){
|
||
RAMModel_json->append(RAM);
|
||
}
|
||
object->insert("Net_Card",*RAMModel_json);
|
||
delete RAMModel_json;
|
||
QJsonArray *netCards_json=new QJsonArray;
|
||
for(auto netCard:netCards){
|
||
netCards_json->append(netCard);
|
||
}
|
||
object->insert("Net_Card",*netCards_json);
|
||
delete netCards_json;
|
||
QJsonArray *audioCards_json=new QJsonArray;
|
||
for(auto audioCard:audioCards){
|
||
audioCards_json->append(audioCard);
|
||
}
|
||
object->insert("Audio_Card",*audioCards_json);
|
||
delete audioCards_json;
|
||
object->insert("Monitor",monitor);
|
||
device->setObject(*object);
|
||
delete object;
|
||
QJsonObject obj_root=qJsonDocument.object();
|
||
obj_root.insert("data",QString(device->toJson()));
|
||
delete device;
|
||
qJsonDocument.setObject(obj_root);
|
||
timer = new QTimer(this);
|
||
QNetworkAccessManager *httpMgr = new QNetworkAccessManager();
|
||
QNetworkRequest requestInfo;
|
||
//HTTP请求
|
||
//请求头
|
||
requestInfo.setUrl(QUrl(DEVICE_URL));
|
||
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
|
||
//保存响应的变量
|
||
reply = httpMgr->post(requestInfo,qJsonDocument.toJson());
|
||
//开启一个循环,直到超时或者获取到数据为止
|
||
connect(reply,&QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
|
||
//设置定时器防止超时
|
||
connect(timer,&QTimer::timeout,this,&DeviceRequest::cancelDownload);
|
||
timer->start(5000);
|
||
//启动循环
|
||
eventLoop.exec();
|
||
delete httpMgr;
|
||
}
|