This commit is contained in:
DevWiki 2024-09-30 18:21:09 +08:00
parent 5c8f902c11
commit 8e1a01215d
5 changed files with 323 additions and 21 deletions

View File

@ -0,0 +1,175 @@
//
// Created by zyz on 2024/9/30.
//
#include "PerformanceTool.h"
#include "../Utils/StringUtil.h"
#include <Psapi.h>
#include <TlHelp32.h>
#include <Windows.h>
#include <powersetting.h>
#include <tchar.h>
#include <numeric>
#include <vector>
#include <thread>
#include <string>
#include <windows.h>
#include <psapi.h>
#include <string>
#include <tchar.h>
#include <iostream>
#pragma comment(lib, "PowrProf.lib")
#pragma comment(lib, "pdh.lib")
WinDevice::PerformanceTool::PerformanceTool() {
}
WinDevice::PerformanceTool::~PerformanceTool() {
}
float WinDevice::PerformanceTool::GetAppCpuUsage(DWORD processId) {
return _GetAppCpuUsage(processId, _GetProcessName(processId));
}
float WinDevice::PerformanceTool::GetAppCpuUsage(const std::wstring &processName) {
return _GetAppCpuUsage(_GetProcessId(processName), processName);
}
float WinDevice::PerformanceTool::_GetAppCpuUsage(DWORD processId, const std::wstring &processName) {
HQUERY query;
PDH_HCOUNTER cpuCounter;
PDH_FMT_COUNTERVALUE counterVal;
TCHAR szCounterPath[MAX_PATH];
// 初始化PDH
if (PdhOpenQuery(NULL, 0, &query) != ERROR_SUCCESS) {
return 1;
}
// 构造CPU计数器路径
_stprintf_s(szCounterPath, MAX_PATH, TEXT("\\Process V2(%s:%d)\\%% Processor Time"), WinDevice::Wstring2String(processName).c_str(), processId);
if (PdhAddCounter(query, szCounterPath, 0, &cpuCounter) != ERROR_SUCCESS) {
PdhCloseQuery(query);
return 1;
}
PdhCollectQueryData(query);
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 等待以获取更新数据
// 再次收集数据
PdhCollectQueryData(query);
// 读取计数器值
auto cpuUsage = 0.0;
auto result = PdhGetFormattedCounterValue(cpuCounter, PDH_FMT_DOUBLE, NULL, &counterVal);
if (result == ERROR_SUCCESS) {
cpuUsage = counterVal.doubleValue;
}
// 清理
// 关闭句柄
PdhRemoveCounter(cpuCounter);
PdhCloseQuery(query);
return cpuUsage;
}
float WinDevice::PerformanceTool::GetAppMemoryUsage(const std::wstring &processName) {
return _GetAppMemoryUsage(processName);
}
float WinDevice::PerformanceTool::GetAppMemoryUsage(DWORD processId) {
return _GetAppMemoryUsage(_GetProcessName(processId));
}
float WinDevice::PerformanceTool::_GetAppMemoryUsage(const std::wstring &processName) {
HQUERY query;
PDH_HCOUNTER memCounter;
PDH_FMT_COUNTERVALUE counterVal;
TCHAR szCounterPath[MAX_PATH];
// 初始化PDH
if (PdhOpenQuery(NULL, 0, &query) != ERROR_SUCCESS) {
return 1;
}
// 构造内存计数器路径
_stprintf_s(szCounterPath, MAX_PATH, TEXT("\\Process(%s)\\%s"), processName.c_str(), TEXT("Working Set - Private"));
if (PdhAddCounter(query, szCounterPath, 0, &memCounter) != ERROR_SUCCESS) {
PdhCloseQuery(query);
return 1;
}
PdhCollectQueryData(query);
auto memoryUsage = 0.0;
auto result = PdhGetFormattedCounterValue(memCounter, PDH_FMT_DOUBLE, NULL, &counterVal);
if (result == ERROR_SUCCESS) {
memoryUsage = counterVal.doubleValue / 1024.0 / 1024.0;
}
// 清理
// 关闭句柄
PdhRemoveCounter(memCounter);
PdhCloseQuery(query);
return memoryUsage;
}
std::wstring WinDevice::PerformanceTool::_GetProcessName(DWORD processId) {
std::wstring processName = L"<unknown>"; // 使用 std::wstring
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (hProcess != nullptr) {
HMODULE hMod;
DWORD cbNeeded;
// 获取进程中的模块句柄
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
// 获取模块的可执行文件名
TCHAR name[MAX_PATH];
GetModuleBaseName(hProcess, hMod, name, sizeof(name) / sizeof(TCHAR));
// 去掉 .exe 后缀
TCHAR* dot = _tcsrchr(name, '.');
if (dot != nullptr && _tcscmp(dot, TEXT(".exe")) == 0) {
*dot = '\0'; // 将 '.' 及其后面的字符替换为 '\0'
}
processName = WinDevice::TCHARArrayToWString(name); // 转换为 std::wstring
}
CloseHandle(hProcess); // 确保在这里关闭句柄
}
// 打印进程名称
std::wcout << L"Current process name: " << processName << std::endl;
return processName; // 返回 std::wstring
}
DWORD WinDevice::PerformanceTool::_GetProcessId(const std::wstring &processName) {
DWORD processId = 0;
//创建进程快照
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return 0;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
// 遍历所有进程
if (Process32First(hSnapshot, &pe))
{
do
{
// 将进程名与目标进程名进行比较
if (_tcscmp(pe.szExeFile, WinDevice::Wstring2String(processName).c_str()) == 0)
{
processId = pe.th32ProcessID;
break;
}
} while (Process32Next(hSnapshot, &pe));
}
return processId;
}

View File

@ -0,0 +1,47 @@
//
// Created by zyz on 2024/9/30.
//
#include <WTypesbase.h>
#include <Pdh.h>
#include <PdhMsg.h>
#include <vector>
#include <string>
#ifndef WINDEVICE_PERFORMANCETOOL_H
#define WINDEVICE_PERFORMANCETOOL_H
namespace WinDevice {
struct AppUsageInfo {
DWORD processId;
std::string processName;
float cpuUsage;
float memoryUsage;
};
class PerformanceTool {
public:
PerformanceTool();
~PerformanceTool();
float GetAppCpuUsage(DWORD processId);
float GetAppCpuUsage(const std::wstring& processName);
float GetAppMemoryUsage(DWORD processId);
float GetAppMemoryUsage(const std::wstring& processName);
// float GetCurrentAppCpuUsage();
// float GetCurrentAppMemoryUsage();
// WinDevice::AppUsageInfo GetCurrentAppUsage();
// WinDevice::AppUsageInfo GetAppUsage(DWORD processId);
// WinDevice::AppUsageInfo GetAppUsage(const std::wstring& processName);
// std::vector<WinDevice::AppUsageInfo> GetTopAppUsageInfo(int topCount);
// float GetTotalCpuUsage() const;
// float GetTotalMemoryUsage() const;
private:
float _GetAppCpuUsage(DWORD processId, const std::wstring &processName);
float _GetAppMemoryUsage(const std::wstring &processName);
std::wstring _GetProcessName(DWORD processId);
DWORD _GetProcessId(const std::wstring &processName);
};
}
#endif //WINDEVICE_PERFORMANCETOOL_H

View File

@ -0,0 +1,70 @@
//
// Created by zyz on 2024/9/30.
//
#ifndef WINDEVICE_STRINGUTIL_CPP_H
#define WINDEVICE_STRINGUTIL_CPP_H
#include "StringUtil.h"
#include <windows.h>
#include <string>
#include <locale>
#include <codecvt>
template<typename To, typename From>
To Convert(const From &input) {
std::wstring_convert<std::codecvt_utf8<typename From::value_type>, typename From::value_type> converter;
try {
return converter.to_bytes(input);
} catch (...) {
return To(); // 返回空对象
}
}
std::string WinDevice::Wstring2String(const std::wstring &input) {
return Convert<std::string>(input);
}
std::string WinDevice::Wchar2String(const WCHAR *input) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
try {
return converter.to_bytes(input);
} catch (...) {
return ""; // 返回空字符串表示失败
}
}
std::wstring WinDevice::String2Wstring(const std::string &input) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
try {
return converter.from_bytes(input);
} catch (...) {
return L""; // 返回空宽字符串表示失败
}
}
wchar_t *WinDevice::String2Wchar(const std::string &input) {
std::wstring wstr = String2Wstring(input);
if (wstr.empty()) {
return nullptr; // 转换失败时返回 nullptr
}
wchar_t *wcharStr = new wchar_t[wstr.length() + 1];
std::wcscpy(wcharStr, wstr.c_str());
return wcharStr; // 返回动态分配的 wchar_t*
}
// 通用转换函数
std::wstring WinDevice::TCHARArrayToWString(const TCHAR *tcharArray) {
#ifdef UNICODE
return std::wstring(tcharArray); // 如果是 Unicode直接返回
#else
// 如果是 ANSI进行转换
int size_needed = MultiByteToWideChar(CP_ACP, 0, tcharArray, -1, nullptr, 0);
std::wstring wstrName(size_needed, L'\0'); // 创建足够大小的 std::wstring
MultiByteToWideChar(CP_ACP, 0, tcharArray, -1, &wstrName[0], size_needed);
return wstrName;
#endif
}
#endif //WINDEVICE_STRINGUTIL_CPP_H

View File

@ -1,22 +1,13 @@
#include <string>
#include <locale>
#include <codecvt>
#pragma once
#include <windows.h>
#include <string>
namespace WinDevice {
template<typename To, typename From>
To Convert(const From& input) {
std::wstring_convert<std::codecvt_utf8<typename From::value_type>, typename From::value_type> converter;
return converter.to_bytes(input);
}
std::string Wstring2String(const std::wstring& input) {
return Convert<std::string>(input);
}
std::string Wchar2String(const WCHAR* input) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(input);
}
std::string Wstring2String(const std::wstring& input);
std::string Wchar2String(const WCHAR* input);
std::wstring String2Wstring(const std::string& input);
wchar_t* String2Wchar(const std::string& input);
std::wstring TCHARArrayToWString(const TCHAR* tcharArray);
}

View File

@ -2,11 +2,30 @@
// Created by zyz on 2023/12/20.
//
#include <iostream>
#include <thread>
#include "Video/ScreenManager.h"
#include "Utils/PerformanceTool.h"
void getInfo() {
WinDevice::PerformanceTool performanceTool;
while (true) {
std::cout << "App CPU Usage: " << performanceTool.GetAppCpuUsage(L"XYWinQT.pak") << "%" << std::endl;
// 每隔一秒采样一次(如果需要的话)
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
WinDevice::ScreenManager screenManager;
screenManager.UpdateDisplayInfo();
// WinDevice::ScreenManager screenManager;
// screenManager.UpdateDisplayInfo();
getInfo();
std::cout << "Press Enter to exit..." << std::endl; // 输出提示信息
std::cin.get(); // 等待用户输入
return 0;
}