【C++】在沒有視窗名稱的情況下確認程式是否開啟

by - 晚上10:18

之前我有寫一篇文章說明如何透過視窗的名稱來得知程式是否有在執行(請參考這裡),但是有時視窗名稱是無法得知(背景程式)或無法預期的,像是"工作管理員"這個程式在WIN10叫"工作管理員",但在WIN7叫"Windows 工作管理員",為了提高程式相容性,我們還有一個辦法:透過執行檔的名稱來確定。
我用的方法是把所有處理程序列舉出來再一一檢查是否有我們要找的執行檔。
我們可以利用tlhelp32.h中所提供的API函式:CreateToolhelp32Snapshot()、Process32First()、Process32Next() 來完成我們要做的事。
先利用函式CreateToolhelp32Snapshot()取得一個處理程序的串列

PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);

上述程式碼中的entry是一個PROCESSENTRY32的結構,宣告在tlhelp32.h內,其原型如下:

typedef struct tagPROCESSENTRY32 {
    DWORD dwSize;
    DWORD cntUsage;
    DWORD th32ProcessID;
    ULONG_PTR th32DefaultHeapID;
    DWORD th32ModuleID;
    DWORD cntThreads;
    DWORD th32ParentProcessID;
    LONG pcPriClassBase;
    DWORD dwFlags;
    CHAR szExeFile[MAX_PATH];
  } PROCESSENTRY32;
  typedef PROCESSENTRY32 *PPROCESSENTRY32;
  typedef PROCESSENTRY32 *LPPROCESSENTRY32;

總之他是用來儲存一些有關處理程序控制代碼等的結構,在這邊是snapshot上的一個「迭代器」

再來用Process32First()來初始化entry

Process32First(snapshot,&entry)

之後就可以用Process32Next()來「暴力」求解了,就是在CreateToolhelp32Snapshot()回傳的串列中一一往下找,並且比對entry中的szExeFile是否與要搜尋的程式執行檔名稱相同就行了。

while (Process32Next(snapshot,&entry)==TRUE){
   string binPath = entry.szExeFile;
   if(binPath.find("test.exe") != wstring::npos){
    cout<<"該程式已開啟,PID:"<<entry.th32ProcessID<<endl;
   }
  }

上述程式碼中的test.exe為要找的程式執行檔名稱。
最後完整的程式碼如下,供各位參考:

#include <windows.h>
#include <stdlib.h>
#include <tlhelp32.h>
#include <string>
#include <iostream>
using namespace std;

int main(){
 PROCESSENTRY32 entry;
 entry.dwSize = sizeof(PROCESSENTRY32);
 HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
 if(Process32First(snapshot,&entry)==TRUE){
  while (Process32Next(snapshot,&entry)==TRUE){
   string binPath = entry.szExeFile;
   if(binPath.find("test.exe") != wstring::npos){
    cout<<"該程式已開啟,PID:"<<entry.th32ProcessID<<endl;
   }
  }
 }
 CloseHandle(snapshot);
 system("pause");
 return 0;
}



你可能會喜歡

2 意見