C/C++:Windows编程—创建进程、终止进程、枚举进程、枚举线程、枚举DLL
創建進程的2種方式
1. 創建進程最簡單的方法
UINT WINAPI WinExec(_In_ LPCSTR lpCmdLine, // 指向可執行文件_In_ UINT uCmdShow // 程序運行后的窗口狀態 );2. CreateProcess函數創建進程
通常情況下,創建一個進程會選擇CreateProcess函數,該函數的參數非常多,功能強大,使用也更為靈活。
https://docs.microsoft.com/zh-cn/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa
BOOL CreateProcessA(LPCSTR lpApplicationName, // 應用程序名LPSTR lpCommandLine, // 命令行參數LPSECURITY_ATTRIBUTES lpProcessAttributes, // 進程安全屬性LPSECURITY_ATTRIBUTES lpThreadAttributes, // 線程安全屬性BOOL bInheritHandles, // 當前進程中的可繼承句柄是否被新進程繼承DWORD dwCreationFlags, // 新進程的優先級以及其他創建標志// DEBUG_PROCESS,DEBUG_ONLY_THIS_PROCESS,CREATE_SUSPENDED ResumeThread() 進行恢復LPVOID lpEnvironment, // 新進程的環境變量 通常這里指定為NULLLPCSTR lpCurrentDirectory, // 指定新進程使用的當前目錄LPSTARTUPINFOA lpStartupInfo, // 新進程的啟動信息,指向STARTUPINFO結構體LPPROCESS_INFORMATION lpProcessInformation //用于返回新進程和主線程的相關信息,指向PROCESS_INFORMATION結構體 );typedef struct _STARTUPINFOA {DWORD cb;LPSTR lpReserved;LPSTR lpDesktop;LPSTR lpTitle;DWORD dwX;DWORD dwY;DWORD dwXSize;DWORD dwYSize;DWORD dwXCountChars;DWORD dwYCountChars;DWORD dwFillAttribute;DWORD dwFlags;WORD wShowWindow;WORD cbReserved2;LPBYTE lpReserved2;HANDLE hStdInput;HANDLE hStdOutput;HANDLE hStdError; } STARTUPINFOA, *LPSTARTUPINFOA; // 該結構體在使用前,需要對cb進行賦值,用戶保存結構體的大小 // 如果要對新進程的輸入輸出重定向的話,會用到該結構體的更多成員// https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/ns-processthreadsapi-process_information typedef struct _PROCESS_INFORMATION {HANDLE hProcess;HANDLE hThread;DWORD dwProcessId;DWORD dwThreadId; } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION; // 該結構體用于返回 新創建進程的句柄和進程ID,進程主線程的句柄和主線程ID,進程創建后 這2個句柄需要關閉示例代碼
#include <windows.h> #include <stdio.h> #define EXEC_FILE "c:\\windows\\system32\\notepad.exe"int main() {// 必須初始化 STARTUPINFOA sInfo = {0};sInfo.cb = sizeof(sInfo); PROCESS_INFORMATION pInfo = {0};BOOL ret = CreateProcessA(EXEC_FILE,NULL,NULL,NULL,FALSE,NULL,NULL,NULL,&sInfo,&pInfo);if(!ret){printf("創建進程失敗");} else{printf("創建進程成功");}CloseHandle(pInfo.hProcess);CloseHandle(pInfo.hThread); return 0; }終止進程
進程正常退出時,會調用ExitProcess函數,調用SendMessage函數發送WM_CLOSE消息到目標窗口的方法,這種方法通常也會讓程序正常結束而退出。本節 介紹 強制結束指定進程。使用OpenProcess獲取進程句柄,然后TerminateProcess終止進程。
FindWindow() // 查找窗口
// 獲取進程ID函數
DWORD WINAPI GetWindowThreadProcessId(
In HWND hWnd, // 窗口句柄
Out_opt LPDWORD lpdwProcessId // 進程ID,傳出參數
);
// 獲取進程句柄,error return NULL
HANDLE WINAPI OpenProcess(
In DWORD dwDesiredAccess, // 打開進程的訪問權限 PROCESS_ALL_ACCESS
In BOOL bInheritHandle, // 是否可繼承
In DWORD dwProcessId // 進程ID
);
// 結束進程
BOOL WINAPI TerminateProcess(
In HANDLE hProcess,
In UINT uExitCode
);
進程、線程及DLL枚舉API介紹
無論是枚舉進程還是枚舉進程中的DLL文件,方法都是相同的,都是通過創建指定的相關快照,再通過循環逐條獲取快照的內容。類似的枚舉線程、枚舉堆都是相同的方法,差別只是在創建快照時的參數不同,逐條獲取快照的內容時的API函數不同而已。
枚舉進程的API函數:CreateToolhelp32Snapshot()、Process32First()、Process32Next()。
枚舉線程的API函數:CreateToolhelp32Snapshot()、Thread32First()、Thread32Next()。
枚舉進程的DLL文件:CreateToolhelp32Snapshot()、Module32First()、Module32Next()。
// err,return INVALID_HANDLE_VALUE HANDLE WINAPI CreateToolhelp32Snapshot(// 建立系統快照的類型:TH32CS_SNAPMODULE,TH32CS_SNAPPROCESS,TH32CS_SNAPTHREAD_In_ DWORD dwFlags,// 如果枚舉的是進程或者系統中的線程 該參數為NULL,如果是進程的DLL 那么該參數是進程ID_In_ DWORD th32ProcessID );// err,return FALSE BOOL WINAPI Process32First(_In_ HANDLE hSnapshot,_Inout_ LPPROCESSENTRY32 lppe // 輸入輸出 );typedef struct tagPROCESSENTRY32 {DWORD dwSize; // 該成員必須賦值,為結構體的大小DWORD cntUsage;DWORD th32ProcessID; // 進程IDULONG_PTR th32DefaultHeapID;DWORD th32ModuleID;DWORD cntThreads;DWORD th32ParentProcessID; // 父進程IDLONG pcPriClassBase;DWORD dwFlags;TCHAR szExeFile[MAX_PATH]; // 可執行文件的文件名 } PROCESSENTRY32, *PPROCESSENTRY32;BOOL WINAPI Process32Next(_In_ HANDLE hSnapshot,_Out_ LPPROCESSENTRY32 lppe // 傳出參數 );// 枚舉進程中加載的DLL 和枚舉系統中的線程都和上2個函數類似,所不同的是 XXX32First() 和 XXX32Next() 第二個參數指向的結構體不同 // DLL 指向的結構體 typedef struct tagMODULEENTRY32 {DWORD dwSize;DWORD th32ModuleID;DWORD th32ProcessID;DWORD GlblcntUsage;DWORD ProccntUsage;BYTE *modBaseAddr;DWORD modBaseSize;HMODULE hModule;TCHAR szModule[MAX_MODULE_NAME32 + 1];TCHAR szExePath[MAX_PATH]; } MODULEENTRY32, *PMODULEENTRY32; // 線程 指向的結構體 typedef struct tagTHREADENTRY32 {DWORD dwSize;DWORD cntUsage;DWORD th32ThreadID;DWORD th32OwnerProcessID;LONG tpBasePri;LONG tpDeltaPri;DWORD dwFlags; } THREADENTRY32, *PTHREADENTRY32;枚舉進程
HANDLE snapHandele = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);if( INVALID_HANDLE_VALUE == snapHandele){qDebug() << "CreateToolhelp32Snapshot error" ;return;}PROCESSENTRY32 entry = {0};entry.dwSize = sizeof(entry);// 長度必須賦值BOOL ret = Process32First(snapHandele,&entry);int i = 0;while (ret) {QString exeFile = QString::fromWCharArray(entry.szExeFile);ui->processTab->insertRow(i);ui->processTab->setItem(i,0,new QTableWidgetItem(exeFile));ui->processTab->setItem(i,1,new QTableWidgetItem(QString("%1").arg(entry.th32ProcessID)));i++;ret = Process32Next(snapHandele,&entry);}CloseHandle(snapHandele);枚舉線程
下面是停止進程,實際上就是停止進程的所有線程,就用到了 枚舉線程
HANDLE snapHandele = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);if( INVALID_HANDLE_VALUE == snapHandele){qDebug() << "CreateToolhelp32Snapshot error" ;return;}THREADENTRY32 entry = {0};entry.dwSize = sizeof(entry);BOOL ret = Thread32First(snapHandele,&entry);while( ret ){if( entry.th32OwnerProcessID == pid){HANDLE tHandle = OpenThread(THREAD_ALL_ACCESS,FALSE,entry.th32ThreadID);if( tHandle == NULL){qDebug() << "OpenThread error,threadId = " << entry.th32ThreadID;}else{DWORD ret = SuspendThread(tHandle);if( ret == -1){qDebug() << "SuspendThread error";}else{qDebug() << "SuspendThread success";}CloseHandle(tHandle);}}ret = Thread32Next(snapHandele,&entry);}CloseHandle(snapHandele);枚舉DLL
HANDLE snapHandele = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE ,pid);if( INVALID_HANDLE_VALUE == snapHandele){qDebug() << "CreateToolhelp32Snapshot error" ;return;}MODULEENTRY32 entry = {0};entry.dwSize = sizeof(entry);// 長度必須賦值BOOL ret = Module32First(snapHandele,&entry);int i = 0;while (ret) {QString dllFile = QString::fromWCharArray(entry.szModule);QString dllPath = QString::fromWCharArray(entry.szExePath);ui->dllTab->insertRow(i);ui->dllTab->setItem(i,0,new QTableWidgetItem(dllFile));ui->dllTab->setItem(i,1,new QTableWidgetItem(QString("%1").arg(dllPath)));i++;ret = Module32Next(snapHandele,&entry);}CloseHandle(snapHandele);總結
以上是生活随笔為你收集整理的C/C++:Windows编程—创建进程、终止进程、枚举进程、枚举线程、枚举DLL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmake,CMakeLists.txt
- 下一篇: C/C++:Windows编程—IAT