C++ 软件使用时间统计
// FileName: UseSoftTime.h #pragma once #include <vector> struct UseTime { // 开始时间 SYSTEMTIME startTime; // 结束时间 SYSTEMTIME endTime; // 时间差 SYSTEMTIME subTime; }; struct UseSoftInfo { // 软件名 CString SoftName; // 软件启动时间;如果在打开我们的软件之前,待监测软件已存在,默认启动时间为我们软件打开的时间 std::vector<UseTime> useTime; // 累计使用时间 SYSTEMTIME allTime; // 使用次数 unsigned int nCount; // 状态 bool bStatus; }; class SoftTime { public: // 软件使用时间 std::vector<UseSoftInfo> m_SoftUseTime; private: // 定时器处理函数 static void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime); // 提权 BOOL EnableDebugPrivilege (BOOL fEnable); // 计算时间差 SYSTEMTIME SubTime (SYSTEMTIME t1, SYSTEMTIME t2); // 计算累计时间 SYSTEMTIME AddTime (SYSTEMTIME t1, SYSTEMTIME t2); // 判断是否为系统进程 bool IsSystemProcess (LPCTSTR lpProName); // 初始化时间为0 void InitTime (SYSTEMTIME& st); public: SoftTime(); ~SoftTime(); public: // 初始化进程信息 void InitProcessName (void); };
// FileName: UseSoftTime.cpp #include "stdafx.h" // 如果编译出错请删除此行 #include "UseSoftTime.h" #include "TlHelp32.h" #include "StrSafe.h" #include "Psapi.h" // 防止错误 error LNK2019 #pragma comment(lib, "psapi.lib") // 全局变量 SoftTime * g_pSoftTime = NULL; SoftTime::SoftTime() { g_pSoftTime = this; } SoftTime::~SoftTime() { if (g_pSoftTime != NULL) { g_pSoftTime = NULL; } } void CALLBACK SoftTime::TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime) { SoftTime * pSoftTimeInfo = (SoftTime*)g_pSoftTime; // 当前系统普通进程的进程名称 std::vector<CString> currentProcessName; HANDLE hProcessSnap = NULL; HANDLE hProcessDll = NULL; BOOL bRet = FALSE; // 初始化dwSize为0,不然Process32First执行失败 PROCESSENTRY32 pe32 = {0}; MODULEENTRY32 me32; LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dwError; LPCTSTR pszFormat = TEXT("开始服务时遇到错误! %s"); if(!pSoftTimeInfo->EnableDebugPrivilege(1)) { MessageBox(NULL, _T("提权失败!"), _T("提示"), MB_OK|MB_ICONEXCLAMATION); } hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { dwError = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM| FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LPTSTR(&lpMsgBuf), 0, NULL); lpDisplayBuf = (LPVOID)LocalAlloc( LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen(pszFormat))*sizeof(TCHAR)); // 格式化字符串 StringCchPrintf( (LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf), // 字节数 pszFormat, lpMsgBuf); CString strTemp; strTemp.Format(TEXT("错误编码为:%d"), dwError); ::MessageBox(NULL, (LPCTSTR)lpDisplayBuf, strTemp, MB_OK|MB_ICONEXCLAMATION); // 清理分配的内存 LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); return; } pe32.dwSize = sizeof(PROCESSENTRY32); Module32First(hProcessSnap, &me32); if (Process32First(hProcessSnap, &pe32)) { do { WCHAR path[MAX_PATH]={0}; HMODULE hModule; HANDLE hProcess; DWORD needed; hProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pe32.th32ProcessID); if (hProcess) { // 枚举进程 EnumProcessModules(hProcess, &hModule, sizeof(hModule), &needed); // 获取进程的全路径 memset(path, 0, sizeof(WCHAR)*MAX_PATH); GetModuleFileNameEx(hProcess, hModule, path, sizeof(WCHAR)*MAX_PATH); if (!(pSoftTimeInfo->IsSystemProcess(path))) { std::vector<CString>::iterator iter; bool bIsExist = false; for (iter=currentProcessName.begin(); iter!=currentProcessName.end(); iter++) { if (*iter ==pe32.szExeFile) { bIsExist = true; } } if (!bIsExist) { currentProcessName.push_back(pe32.szExeFile); } } } } while (Process32Next(hProcessSnap, &pe32)); } // 查找已存在的进程 std::vector<UseSoftInfo>::iterator iter1; std::vector<CString >::iterator iter2; for (iter2=currentProcessName.begin(); iter2!=currentProcessName.end(); iter2++) { bool bIsExist = false; int nIndex = 0; for (iter1=pSoftTimeInfo->m_SoftUseTime.begin(); iter1!=pSoftTimeInfo->m_SoftUseTime.end(); iter1++, nIndex++) { // 已存在的进程,更新软件使用时间 if (*iter2 == iter1->SoftName) { // 进程已存在; bIsExist = true; if (iter1->bStatus) { SYSTEMTIME st; GetLocalTime(&st); int n = pSoftTimeInfo->m_SoftUseTime[nIndex].nCount - 1; //pSoftTimeInfo->m_SoftUseTime[nIndex].allTime = pSoftTimeInfo->SubTime(pSoftTimeInfo->m_SoftUseTime[nIndex].useTime[n].startTime, st); pSoftTimeInfo->m_SoftUseTime[nIndex].useTime[n].subTime = pSoftTimeInfo->SubTime(pSoftTimeInfo->m_SoftUseTime[nIndex].useTime[n].startTime, st); std::vector<UseTime>::iterator iter; pSoftTimeInfo->InitTime(st); for (iter=pSoftTimeInfo->m_SoftUseTime[nIndex].useTime.begin(); iter!=pSoftTimeInfo->m_SoftUseTime[nIndex].useTime.end(); iter++) { st = pSoftTimeInfo->AddTime(st, iter->subTime); } pSoftTimeInfo->m_SoftUseTime[nIndex].allTime = st; } else // 第二次以后打开的情况 { pSoftTimeInfo->m_SoftUseTime[nIndex].nCount += 1; pSoftTimeInfo->m_SoftUseTime[nIndex].bStatus = true; UseTime useTime; GetLocalTime(&useTime.startTime); pSoftTimeInfo->InitTime(useTime.endTime); pSoftTimeInfo->InitTime(useTime.subTime); pSoftTimeInfo->m_SoftUseTime[nIndex].useTime.push_back(useTime); } } } // 新添加的进程 if (!bIsExist) { UseSoftInfo infoTemp; UseTime useTime; GetLocalTime(&useTime.startTime); pSoftTimeInfo->InitTime(useTime.endTime); pSoftTimeInfo->InitTime(useTime.subTime); infoTemp.useTime.push_back(useTime); infoTemp.SoftName = pe32.szExeFile; pSoftTimeInfo->InitTime(infoTemp.allTime); infoTemp.nCount = 1; infoTemp.bStatus = true; pSoftTimeInfo->m_SoftUseTime.push_back(infoTemp); } } // 查找退出的进程 int nIndex = 0; for (iter1=pSoftTimeInfo->m_SoftUseTime.begin(); iter1!=pSoftTimeInfo->m_SoftUseTime.end(); iter1++, nIndex++) { bool bIsExist = false; for (iter2=currentProcessName.begin(); iter2!=currentProcessName.end(); iter2++) { if (iter1->SoftName == *iter2) { bIsExist = true; } } // 退出的进程 if (!bIsExist && pSoftTimeInfo->m_SoftUseTime[nIndex].bStatus) { SYSTEMTIME st; GetLocalTime(&st); pSoftTimeInfo->m_SoftUseTime[nIndex].useTime[pSoftTimeInfo->m_SoftUseTime[nIndex].nCount-1].endTime = st; pSoftTimeInfo->m_SoftUseTime[nIndex].useTime[pSoftTimeInfo->m_SoftUseTime[nIndex].nCount-1].subTime = \ pSoftTimeInfo->SubTime(pSoftTimeInfo->m_SoftUseTime[nIndex].useTime[pSoftTimeInfo->m_SoftUseTime[nIndex].nCount-1].startTime, st); std::vector<UseTime>::iterator iter; pSoftTimeInfo->InitTime(st); for (iter=pSoftTimeInfo->m_SoftUseTime[nIndex].useTime.begin(); iter!=pSoftTimeInfo->m_SoftUseTime[nIndex].useTime.end(); iter++) { st = pSoftTimeInfo->AddTime(st, iter->subTime); } //pSoftTimeInfo->m_SoftUseTime[nIndex].allTime = st; pSoftTimeInfo->m_SoftUseTime[nIndex].bStatus = false; } } // 关闭特权 pSoftTimeInfo->EnableDebugPrivilege(0); // 关闭内核对象 CloseHandle(hProcessSnap ); } BOOL SoftTime::EnableDebugPrivilege (BOOL fEnable) { BOOL fOk = FALSE; HANDLE hToken; // 得到进程的访问令牌 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,&hToken)) { TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; // 查看系统特权值并返回一个LUID结构体 LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0; // 启用/关闭 特权 AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); fOk = (GetLastError() == ERROR_SUCCESS); CloseHandle(hToken); } else { return 0; } return(fOk); } void SoftTime::InitProcessName (void) { HANDLE hProcessSnap = NULL; HANDLE hProcessDll = NULL; BOOL bRet = FALSE; // 初始化dwSize为0,不然Process32First执行失败 PROCESSENTRY32 pe32 = {0}; MODULEENTRY32 me32; LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dwError; LPCTSTR pszFormat = TEXT("开始服务时遇到错误! %s"); if(!EnableDebugPrivilege(1)) { MessageBox(NULL, _T("提权失败!"), _T("提示"), MB_OK|MB_ICONEXCLAMATION); } hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { dwError = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM| FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LPTSTR(&lpMsgBuf), 0, NULL); lpDisplayBuf = (LPVOID)LocalAlloc( LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen(pszFormat))*sizeof(TCHAR)); // 格式化字符串 StringCchPrintf( (LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf), // 字节数 pszFormat, lpMsgBuf); CString strTemp; strTemp.Format(TEXT("错误编码为:%d"), dwError); ::MessageBox(NULL, (LPCTSTR)lpDisplayBuf, strTemp, MB_OK|MB_ICONEXCLAMATION); // 清理分配的内存 LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); return; } pe32.dwSize = sizeof(PROCESSENTRY32); Module32First(hProcessSnap, &me32); if (Process32First(hProcessSnap, &pe32)) { do { WCHAR path[MAX_PATH]={0}; HMODULE hModule; HANDLE hProcess; DWORD needed; hProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pe32.th32ProcessID); if (hProcess) { // 枚举进程 EnumProcessModules(hProcess, &hModule, sizeof(hModule), &needed); // 获取进程的全路径 memset(path, 0, sizeof(WCHAR)*MAX_PATH); GetModuleFileNameEx(hProcess, hModule, path, sizeof(WCHAR)*MAX_PATH); // 普通进程 if (!IsSystemProcess(path)) { UseSoftInfo infoTemp; UseTime useTime; GetLocalTime(&useTime.startTime); InitTime(useTime.endTime); InitTime(useTime.subTime); infoTemp.useTime.push_back(useTime); infoTemp.SoftName = pe32.szExeFile; std::vector<UseSoftInfo>::iterator iter; bool IsExist = false; for (iter=m_SoftUseTime.begin(); iter!=m_SoftUseTime.end(); iter++) { if (iter->SoftName == infoTemp.SoftName) { IsExist = true; } } if (!IsExist) { InitTime(infoTemp.allTime); infoTemp.nCount = 1; infoTemp.bStatus = true; m_SoftUseTime.push_back(infoTemp); } } } } while (Process32Next(hProcessSnap, &pe32)); } // 关闭特权 EnableDebugPrivilege(0); // 关闭内核对象 CloseHandle(hProcessSnap ); // 设置一个定时器 ::SetTimer(NULL, 1, 1000, TimerProc); } bool SoftTime::IsSystemProcess (LPCTSTR lpProName) { CString strTemp(lpProName); strTemp.MakeLower(); if (strTemp.Find(_T("windows")) != -1) { return true; } else if (strTemp == _T("")) { return true; } else if (strTemp.Find(_T("system32")) != -1) { return true; } else { return false; } } SYSTEMTIME SoftTime::SubTime (SYSTEMTIME t1, SYSTEMTIME t2) { t2.wYear -= t1.wYear; t2.wMonth -= t1.wMonth; t2.wDay -= t1.wDay; if (t2.wHour >= t1.wHour) { t2.wHour -= t1.wHour; } else { t2.wDay -= 1; t2.wHour = 24 - t1.wHour + t2.wHour; } if (t2.wMinute >= t1.wMinute) { t2.wMinute -= t1.wMinute; } else { t2.wHour -= 1; t2.wMinute = 60 - t1.wMinute + t2.wMinute; } if (t2.wSecond >= t1.wSecond) { t2.wSecond -= t1.wSecond; } else { t2.wMinute -= 1; t2.wSecond = 60 - t1.wSecond + t2.wSecond; } return t2; } void SoftTime::InitTime (SYSTEMTIME& st) { st.wYear = 0; st.wMonth = 0; st.wDay = 0; st.wHour = 0; st.wMinute = 0; st.wSecond = 0; } SYSTEMTIME SoftTime::AddTime (SYSTEMTIME t1, SYSTEMTIME t2) { t1.wSecond += t2.wSecond; if (t1.wSecond >= 60) { t1.wSecond -= 60; t1.wMinute += 1; } t1.wMinute += t2.wMinute; if (t1.wMinute > 60) { t1.wMinute -= 60; t1.wHour += 1; } t1.wHour += t2.wHour; return t1; }