欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

windows下的获取当前进程使用资源信息

程序员文章站 2022-05-25 23:47:33
...

在一些windows程序中需求需要分析当前程序运行的状态,那么就需要程序自己去捕获自己当前的所使用资源信息。这里上传一个封装好了的程序。

CPU_MEMusage.h

#include <Windows.h>   
#include <stdint.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <string>
#include <crtdbg.h> 

#pragma warning(disable:4996)
//原理:调用GetProcessTimes(),并与上次调用得到的结果相减,即得到某段时间内CPU的使用时间  
//C++ 获取特定进程规定CPU使用率  原文:http://blog.csdn.net/liuqx97bb/article/details/52058657  
class CPU_MEMusage {
private:
	typedef long long          int64_t;
	typedef unsigned long long uint64_t;
	HANDLE _hProcess;
	int _processor;    //cpu数量    
	int64_t _last_time;         //上一次的时间    
	int64_t _last_system_time;


	// 时间转换    
	uint64_t file_time_2_utc(const FILETIME* ftime);

	// 获得CPU的核数    
	int get_processor_number();

	//初始化  
	void init()
	{
		_last_system_time = 0;
		_last_time = 0;
		_hProcess = 0;
	}

	//关闭进程句柄  
	void clear()
	{
		if (_hProcess) {
			CloseHandle(_hProcess);
			_hProcess = 0;
		}
	}

public:
	DWORD  ProcessID;//线程pid

	CPU_MEMusage(const char* pName) {
		ProcessID = GetProcessIDByName(pName);
		_processor = get_processor_number();
		setpid(ProcessID);
	}
	CPU_MEMusage() { init(); _processor = get_processor_number(); }
	~CPU_MEMusage() { clear(); }

	//获取进行Pid号
	DWORD GetProcessIDByName(const char* pName);

	//返回值为进程句柄,可判断OpenProcess是否成功  
	HANDLE setpid(DWORD ProcessID) {
		clear();    //如果之前监视过另一个进程,就先关闭它的句柄  
		init();
		return _hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, ProcessID);
	}

	//-1 即为失败或进程已退出; 如果成功,首次调用会返回-2(中途用setpid更改了PID后首次调用也会返回-2)  
	float get_cpu_usage();

	//获取 WIN 硬盘使用情况  
	int getWin_DiskUsage(std::string &info);

	//获取内存使用情况
	int get_memory_usage(uint64_t* mem, uint64_t* vmem)
	{
		PROCESS_MEMORY_COUNTERS pmc;
		if (GetProcessMemoryInfo(_hProcess, &pmc, sizeof(pmc)))
		{
			if (mem) *mem = pmc.WorkingSetSize/1024;
			if (vmem) *vmem = pmc.PagefileUsage/1024;
			return 0;
		}
		return -1;
	};

	int get_io_bytes(uint64_t* read_bytes, uint64_t* write_bytes)
	{
		IO_COUNTERS io_counter;
		if (GetProcessIoCounters(_hProcess, &io_counter))
		{
			if (read_bytes) *read_bytes = io_counter.ReadTransferCount;
			if (write_bytes) *write_bytes = io_counter.WriteTransferCount;
			return 0;
		}
		return -1;
	};

	std::string intToString(int v)
	{
		char buf[32] = { 0 };
		_snprintf(buf, sizeof(buf), "%u", v);

		std::string str = buf;
		return str;
	};
};

CPU_MEMusage.cpp

#include "CPU_MEMusage.h"
#include <iostream>

using namespace std;
float CPU_MEMusage::get_cpu_usage()
{

	FILETIME now;
	FILETIME creation_time;
	FILETIME exit_time;
	FILETIME kernel_time;
	FILETIME user_time;
	int64_t system_time;
	int64_t time;
	int64_t system_time_delta;
	int64_t time_delta;

	DWORD exitcode;

	float cpu = -1;

	if (!_hProcess) return -1;

	GetSystemTimeAsFileTime(&now);

	//判断进程是否已经退出  
	GetExitCodeProcess(_hProcess, &exitcode);
	if (exitcode != STILL_ACTIVE) {
		clear();
		return -1;
	}

	//计算占用CPU的百分比  
	if (!GetProcessTimes(_hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
	{
		clear();
		return -1;
	}
	system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time))
		/ _processor;
	time = file_time_2_utc(&now);

	//判断是否为首次计算  
	if ((_last_system_time == 0) || (_last_time == 0))
	{
		_last_system_time = system_time;
		_last_time = time;
		return 0;
	}

	system_time_delta = system_time - _last_system_time;
	time_delta = time - _last_time;

	if (time_delta == 0) {
		return -1;
	}

	cpu = (float)system_time_delta * 100 / (float)time_delta;
	_last_system_time = system_time;
	_last_time = time;
	return cpu;
}

CPU_MEMusage::uint64_t CPU_MEMusage::file_time_2_utc(const FILETIME* ftime)
{
	LARGE_INTEGER li;

	li.LowPart = ftime->dwLowDateTime;
	li.HighPart = ftime->dwHighDateTime;
	return li.QuadPart;
}

int CPU_MEMusage::get_processor_number()
{
	SYSTEM_INFO info;
	GetSystemInfo(&info);
	return info.dwNumberOfProcessors;
}

//获取 WIN 硬盘使用情况  
int CPU_MEMusage::getWin_DiskUsage(string & info)
{
	int DiskCount = 0;
	DWORD DiskInfo = GetLogicalDrives();
	//利用GetLogicalDrives()函数可以获取系统中逻辑驱动器的数量,函数返回的是一个32位无符号整型数据。    
	while (DiskInfo)//通过循环操作查看每一位数据是否为1,如果为1则磁盘为真,如果为0则磁盘不存在。    
	{
		if (DiskInfo & 1)//通过位运算的逻辑与操作,判断是否为1    
		{
			++DiskCount;
		}
		DiskInfo = DiskInfo >> 1;//通过位运算的右移操作保证每循环一次所检查的位置向右移动一位。       
	}
	info = "Logical Disk Number:" + intToString(DiskCount) + "\n";

	//-----------------------------------------------------------------------------------------     
	char DStr[1024] = { 0 };
	GetLogicalDriveStrings(1024, (LPTSTR)DStr);
	//通过GetLogicalDriveStrings将字符串信息复制到堆区数组中,其中保存了所有驱动器的信息。    

	int DType;
	int si = 0;
	BOOL fResult;
	unsigned _int64 i64FreeBytesToCaller;
	unsigned _int64 i64TotalBytes;
	unsigned _int64 i64FreeBytes;

	for (int i = 0; i< DiskCount; ++i)//为了显示每个驱动器的状态,则通过循环输出实现,由于DStr内部保存的数据是A:\NULLB:\NULLC:\NULL,这样的信息,所以DSLength/4可以获得具体大循环范围    
	{
		char dir[16] = { 0 };
		memcpy(dir, (LPTSTR)DStr + (i * 4), 1);
		strcat(dir, ":");
		info += dir;
		DType = GetDriveType((LPTSTR)DStr + (i * 4));
		//GetDriveType函数,可以获取驱动器类型,参数为驱动器的根目录    
		if (DType == DRIVE_FIXED)
		{
			info += "硬盘:";
		}
		else if (DType == DRIVE_CDROM)
		{
			info += "光驱:";
		}
		else if (DType == DRIVE_REMOVABLE)
		{
			info += "可移动磁盘:";
		}
		else if (DType == DRIVE_REMOTE)
		{
			info += "网络磁盘:";
		}
		else if (DType == DRIVE_RAMDISK)
		{
			info += "虚拟RAM磁盘:";
		}
		else if (DType == DRIVE_UNKNOWN)
		{
			info += "未知设备:";
		}

		fResult = GetDiskFreeSpaceEx(
			(LPTSTR)DStr + i * 4,
			(PULARGE_INTEGER)&i64FreeBytesToCaller,
			(PULARGE_INTEGER)&i64TotalBytes,
			(PULARGE_INTEGER)&i64FreeBytes);
		//GetDiskFreeSpaceEx函数,可以获取驱动器磁盘的空间状态,函数返回的是个BOOL类型数据    
		if (fResult)//通过返回的BOOL数据判断驱动器是否在工作状态    
		{
			info += "totalspace(磁盘总容量):";
			info += intToString((float)i64TotalBytes / 1024 / 1024);
			info += " MB        ";
			info += "freespace(磁盘剩余空间):";
			info += intToString((float)i64FreeBytesToCaller / 1024 / 1024);
			info += " MB\n";    
		}
		else
		{
			cout << " 设备未准备好";
		}
	}

	return 0;
}

DWORD CPU_MEMusage::GetProcessIDByName(const char* pName)
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hSnapshot) {
		return NULL;
	}
	PROCESSENTRY32 pe = { sizeof(pe) };
	int equal = -1;
	for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
		int bufSize = WideCharToMultiByte(CP_ACP, NULL, pe.szExeFile, -1, NULL, 0, NULL, FALSE);
		//std::cout << bufSize << std::endl;
		char *sp = new char[bufSize];
		WideCharToMultiByte(CP_ACP, NULL, pe.szExeFile, -1, sp, bufSize, NULL, FALSE);
		//std::cout << sp << std::endl;
		equal = strcmp(sp, pName);
		delete[] sp;
		if (!equal)
		{
			CloseHandle(hSnapshot);
			return pe.th32ProcessID;
		}
	}
	CloseHandle(hSnapshot);
	return 0;
};

使用示例程序:

main.cpp

#define CRTDBG_MAP_ALLOC
#include "CPU_MEMusage.h"  
#include <stdio.h>
#include <string.h>
#include <iostream>

int main()
{
	CPU_MEMusage usg("systeminfo.exe");
	unsigned int a = 0x10;
	unsigned int b = 0x02;
	unsigned int c = a | b;
	std::cout << c << std::endl;
	while (1)
	//for (int i=0;i<100;i++)
	{
		std::string disk;
		uint64_t mem = 0, vmem = 0, r = 0, w = 0;

		float cpu = usg.get_cpu_usage();
		usg.get_memory_usage(&mem, &vmem);
		usg.get_io_bytes(&r, &w);
		usg.getWin_DiskUsage(disk);
		printf("systeminfo.exe:is pid=%d\ncpu使用率:%.2f%%\n",usg.ProcessID, cpu);
		printf("内存使用: %d KB\n", mem);
		printf("虚拟内存使用: %d KB\n", vmem);
		printf("总共读: %u 字节\n", r);
		printf("总共写: %u 字节\n", w);
		std::cout << disk << std::endl;
		Sleep(500);
		
	}
	_CrtDumpMemoryLeaks();
	return 0;
}