C++ 统计it运行的程序';s类名称
我试图检测应用程序人员运行的实例数。他打开过我的申请表吗?两次?三次? 我试图通过进程名检查它的实例来检测它,但在windows中它是指针-人们可能会更改.exe名称,它不会计入最终的数字 那我怎么办呢?我想用类名(HWND?)而不是进程名来搜索它,但我该怎么做呢 这是我用于按进程名称检测的代码:C++ 统计it运行的程序';s类名称,c++,winapi,C++,Winapi,我试图检测应用程序人员运行的实例数。他打开过我的申请表吗?两次?三次? 我试图通过进程名检查它的实例来检测它,但在windows中它是指针-人们可能会更改.exe名称,它不会计入最终的数字 那我怎么办呢?我想用类名(HWND?)而不是进程名来搜索它,但我该怎么做呢 这是我用于按进程名称检测的代码: int Platform::getMulticlientCount(const std::string& ProcessName) { PROCESSENTRY32 pe32 = {
int Platform::getMulticlientCount(const std::string& ProcessName)
{
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
const char *cstr = ProcessName.c_str();
int counter = 0;
if (Process32First(hSnapshot, &pe32))
{
do
{
if (_tcsicmp(pe32.szExeFile, cstr) == 0)
{
counter++;
}
} while (Process32Next(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
return counter;
}
下面是计算正在运行的实例的示例代码。当应用程序自行计算实例时,是否重命名二进制文件并不重要。我使用了一个文件来保持示例的简单性,但是注册表也可以工作。唯一缺少的是一个全局互斥来保护文件不受并发访问。嗯
#include <iostream>
#include <thread>
#include <fstream>
#include <Windows.h>
class GlobalCounter
{
public:
GlobalCounter(const std::string& id)
: _id(id)
{
const auto filename = "C:\\users\\twollgam\\" + id + ".counter";
if (GlobalFindAtomA(id.c_str()) == 0)
{
std::ofstream(filename) << 1;
std::cout << "I am the first instance." << std::endl;
}
else
{
auto counter = 0;
std::ifstream(filename) >> counter;
++counter;
std::ofstream(filename) << counter;
std::cout << "I am the " << counter << " instance." << std::endl;
}
_atom = GlobalAddAtomA(id.c_str());
}
~GlobalCounter()
{
const auto filename = "C:\\users\\twollgam\\" + _id + ".counter";
auto counter = 0;
std::ifstream(filename) >> counter;
--counter;
std::ofstream(filename) << counter;
GlobalDeleteAtom(_atom);
}
private:
const std::string _id;
ATOM _atom;
};
int main()
{
const auto globalCounter = GlobalCounter("test");
std::cout << "Hello World!\n";
std::this_thread::sleep_for(std::chrono::seconds(30));
return 0;
}
#包括
#包括
#包括
#包括
类全局计数器
{
公众:
全局计数器(常量标准::字符串和id)
:_id(id)
{
const auto filename=“C:\\users\\twollgam\\”+id+“.counter”;
if(GlobalFindAtomA(id.c_str())==0)
{
std::ofstream(filename)Remy的实例:
static int counter;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
char classname[MAX_PATH] = { 0 };
GetClassNameA(hwnd,classname, MAX_PATH);
if (_tcsicmp(classname, (char*)lParam) == 0)
counter++;
return true;
}
int Platform::getMulticlientCount(const std::string& ClassName)
{
counter = 0;
const char *cstr = ClassName.c_str();
EnumWindows(EnumWindowsProc, (LPARAM)cstr);
return counter;
}
如果还需要获取实例,请在EnumWindowsProc
中:
HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
如果还需要获取processId,请在EnumWindowsProc
中:
HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
“我想按类名(HWND?)而不是进程名来搜索它,但是我该怎么做呢?”-请看FindWindow/Ex()
,或者EnumWindows()
和GetClassName()
既然这是您的应用程序,为什么不在启动时增加一个计数器,在应用程序退出时减少它?您必须将该计数器保留在共享内存区域中,例如内存映射文件中。或者使用作为一种快速而脏的方式来监视全局状态。如果应用程序终止而不运行析构函数,则此操作将失败(例如崩溃时)。与内核对象的句柄不同,操作系统不会自动释放全局atom表中字符串的引用计数。而且,由于您使用的是全局atom表,因此应确保使用唯一的名称(例如GUID的字符串表示)。