C/C++:Windows编程—创建进程、终止进程、枚举进程、枚举线程、枚举DLL
創(chuàng)建進程的2種方式
1. 創(chuàng)建進程最簡單的方法
UINT WINAPI WinExec(_In_ LPCSTR lpCmdLine, // 指向可執(zhí)行文件_In_ UINT uCmdShow // 程序運行后的窗口狀態(tài) );2. CreateProcess函數(shù)創(chuàng)建進程
通常情況下,創(chuàng)建一個進程會選擇CreateProcess函數(shù),該函數(shù)的參數(shù)非常多,功能強大,使用也更為靈活。
https://docs.microsoft.com/zh-cn/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa
BOOL CreateProcessA(LPCSTR lpApplicationName, // 應(yīng)用程序名LPSTR lpCommandLine, // 命令行參數(shù)LPSECURITY_ATTRIBUTES lpProcessAttributes, // 進程安全屬性LPSECURITY_ATTRIBUTES lpThreadAttributes, // 線程安全屬性BOOL bInheritHandles, // 當前進程中的可繼承句柄是否被新進程繼承DWORD dwCreationFlags, // 新進程的優(yōu)先級以及其他創(chuàng)建標志// DEBUG_PROCESS,DEBUG_ONLY_THIS_PROCESS,CREATE_SUSPENDED ResumeThread() 進行恢復(fù)LPVOID lpEnvironment, // 新進程的環(huán)境變量 通常這里指定為NULLLPCSTR lpCurrentDirectory, // 指定新進程使用的當前目錄LPSTARTUPINFOA lpStartupInfo, // 新進程的啟動信息,指向STARTUPINFO結(jié)構(gòu)體LPPROCESS_INFORMATION lpProcessInformation //用于返回新進程和主線程的相關(guān)信息,指向PROCESS_INFORMATION結(jié)構(gòu)體 );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; // 該結(jié)構(gòu)體在使用前,需要對cb進行賦值,用戶保存結(jié)構(gòu)體的大小 // 如果要對新進程的輸入輸出重定向的話,會用到該結(jié)構(gòu)體的更多成員// 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; // 該結(jié)構(gòu)體用于返回 新創(chuàng)建進程的句柄和進程ID,進程主線程的句柄和主線程ID,進程創(chuàng)建后 這2個句柄需要關(guān)閉示例代碼
#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("創(chuàng)建進程失敗");} else{printf("創(chuàng)建進程成功");}CloseHandle(pInfo.hProcess);CloseHandle(pInfo.hThread); return 0; }終止進程
進程正常退出時,會調(diào)用ExitProcess函數(shù),調(diào)用SendMessage函數(shù)發(fā)送WM_CLOSE消息到目標窗口的方法,這種方法通常也會讓程序正常結(jié)束而退出。本節(jié) 介紹 強制結(jié)束指定進程。使用OpenProcess獲取進程句柄,然后TerminateProcess終止進程。
FindWindow() // 查找窗口
// 獲取進程ID函數(shù)
DWORD WINAPI GetWindowThreadProcessId(
In HWND hWnd, // 窗口句柄
Out_opt LPDWORD lpdwProcessId // 進程ID,傳出參數(shù)
);
// 獲取進程句柄,error return NULL
HANDLE WINAPI OpenProcess(
In DWORD dwDesiredAccess, // 打開進程的訪問權(quán)限 PROCESS_ALL_ACCESS
In BOOL bInheritHandle, // 是否可繼承
In DWORD dwProcessId // 進程ID
);
// 結(jié)束進程
BOOL WINAPI TerminateProcess(
In HANDLE hProcess,
In UINT uExitCode
);
進程、線程及DLL枚舉API介紹
無論是枚舉進程還是枚舉進程中的DLL文件,方法都是相同的,都是通過創(chuàng)建指定的相關(guān)快照,再通過循環(huán)逐條獲取快照的內(nèi)容。類似的枚舉線程、枚舉堆都是相同的方法,差別只是在創(chuàng)建快照時的參數(shù)不同,逐條獲取快照的內(nèi)容時的API函數(shù)不同而已。
枚舉進程的API函數(shù):CreateToolhelp32Snapshot()、Process32First()、Process32Next()。
枚舉線程的API函數(shù):CreateToolhelp32Snapshot()、Thread32First()、Thread32Next()。
枚舉進程的DLL文件:CreateToolhelp32Snapshot()、Module32First()、Module32Next()。
// err,return INVALID_HANDLE_VALUE HANDLE WINAPI CreateToolhelp32Snapshot(// 建立系統(tǒng)快照的類型:TH32CS_SNAPMODULE,TH32CS_SNAPPROCESS,TH32CS_SNAPTHREAD_In_ DWORD dwFlags,// 如果枚舉的是進程或者系統(tǒng)中的線程 該參數(shù)為NULL,如果是進程的DLL 那么該參數(shù)是進程ID_In_ DWORD th32ProcessID );// err,return FALSE BOOL WINAPI Process32First(_In_ HANDLE hSnapshot,_Inout_ LPPROCESSENTRY32 lppe // 輸入輸出 );typedef struct tagPROCESSENTRY32 {DWORD dwSize; // 該成員必須賦值,為結(jié)構(gòu)體的大小DWORD cntUsage;DWORD th32ProcessID; // 進程IDULONG_PTR th32DefaultHeapID;DWORD th32ModuleID;DWORD cntThreads;DWORD th32ParentProcessID; // 父進程IDLONG pcPriClassBase;DWORD dwFlags;TCHAR szExeFile[MAX_PATH]; // 可執(zhí)行文件的文件名 } PROCESSENTRY32, *PPROCESSENTRY32;BOOL WINAPI Process32Next(_In_ HANDLE hSnapshot,_Out_ LPPROCESSENTRY32 lppe // 傳出參數(shù) );// 枚舉進程中加載的DLL 和枚舉系統(tǒng)中的線程都和上2個函數(shù)類似,所不同的是 XXX32First() 和 XXX32Next() 第二個參數(shù)指向的結(jié)構(gòu)體不同 // DLL 指向的結(jié)構(gòu)體 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; // 線程 指向的結(jié)構(gòu)體 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);總結(jié)
以上是生活随笔為你收集整理的C/C++:Windows编程—创建进程、终止进程、枚举进程、枚举线程、枚举DLL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmake,CMakeLists.txt
- 下一篇: Linux系统编程:lseek扩展文件大