文章标题

来源:互联网 发布:实时数据监控 编辑:程序博客网 时间:2024/06/02 05:34

终止进程/窗口的几种方式

  1. TerminateProcess()
    函数功能: 终止指定进程及其所有线程。
    (由于会关闭整个进程,所以不是特别推荐使用)
函数原型:BOOL TerminateProcess(    HANDLE hProcess,    //需要终止的进程句柄    UINT uExitCode     //进程终止码);参数:    hProcess    [in] 指定要中断进程的句柄. 该句柄可以由 OpenProcess()得到.    DWORD uExitCode    [in] 进程和其所有线程的退出代码返回值:    返回非零值代表成功。0代表失败。想要得到更多错误信息,请调用GetLastError()

OpenProcess();

函数功能: 用来打开一个已存在的进程对象,并返回进程的句柄。
OpenProcess函数执行成功将根据传入参数的PID返回该PID进程的句柄.执行失败返回0.执行失败的错误信息请使用GetLastError 函数.

PID: ProcessID

函数原型:HANDLE OpenProcess(    DWORD dwDesiredAccess,    //渴望得到的访问权限(标志)    BOOL bInheritHandle,      // 是否继承句柄    DWORD dwProcessId         // 进程标示符);

参数说明(通常使用PROCESS_ALL_ACCESS即可):

dwDesiredAccess:
// 指定打开后,该进程的访问权限

PROCESS_ALL_ACCESS
//给予进程所有可能允许的权限.

PROCESS_DUP_HANDLE
//允许使用DuplicateHandle函数进行进程句柄的复制操作.

PROCESS_QUERY_INFORMATION
//允许函数GetExitCodeProcess 或函数GetPriorityClass functions查询进程的信息时使用该句柄.

PROCESS_SET_INFORMATION//允许函数SetPriorityClass使用此句柄进行优先级设置.

PROCESS_TERMINATE//允许函数TerminateProcess 使用此句柄关闭进程.

PROCESS_VM_OPERATION //允许函数VirtualProtectEx使用此句柄修改进程的虚拟内存.

PROCESS_VM_READ or PROCESS_VM_WRITE //允许函数访问和写入权限

SYNCHRONIZE Windows NT //专用: 允许同步函数使用此句柄.

bInheritHandle: //指定返回的句柄是继承dwProcessId指定的进程..

dwProcessId://指定打开需要打开的进程的PID.

特别注明:对于自己创造的进程可以使用已有的句柄,对于该程序中未出现的句柄,可以使用进程快照来获得句柄

进程快照函数:

  • CreateToolhelp32Snapshot()
  • Process32First()
  • Process32Next()
  • CloseHandle()//在此仅仅是提醒不要忘记关闭已用的句柄

列表内容
1. CreateToolhelp32Snapshot()
函数功能:
函数通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照.说到底,可以获取系统中正在运行的进程信息,线程信息,等

HANDLE WINAPI CreateToolhelp32Snapshot(    DWORD dwFlags,    //用来指定“快照”中需要返回的对象,可以是TH32CS_SNAPPROCESS等    DWORD th32ProcessID    //一个进程ID号,用来指定要获取哪一个进程的快照,当获取系统进程列表或获取 当前进程快照时可以设为0);

dwFlags
指定快照中包含的系统内容,这个参数能够使用下列数值(常量)中的一个或多个。
TH32CS_INHERIT - 声明快照句柄是可继承的。
TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程。
TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆。
TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块。
TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程。
TH32CS_SNAPTHREAD - 在快照中包含系统中所有的线程。
Const TH32CS_SNAPHEAPLIST = &H1
Const TH32CS_SNAPPROCESS = &H2
Const TH32CS_SNAPTHREAD = &H4
Const TH32CS_SNAPMODULE = &H8
Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE)
Const TH32CS_INHERIT = &H80000000
th32ProcessID
指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE后才有效,在其他情况下该参数被忽略,所有的进程都会被快照。
返回值:
调用成功,返回快照的句柄,调用失败,返回INVALID_HANDLE_VALUE 。
备注:
使用GetLastError函数查找该函数产生的错误状态码。
注意,在Win NT中,要删除快照,使用CloseHandle函数;在Win CE中,要删除快照,使用CloseToolhelp32Snapshot函数。

Process32First()
函数功能:
一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照后,我们可以利用process32First函数来获得第一个进程的句柄

BOOL WINAPI Process32First(    HANDLE hSnapshot,//_in    LPPROCESSENTRY32 lppe//_out);//其中PROCESSENTRY32结构为://PROCESSENTRY32 结构如下:typedef struct tagPROCESSENTRY32 {    DWORD dwSize; // 结构大小;    DWORD cntUsage; // 此进程的引用计数;    DWORD th32ProcessID; // 进程ID;    DWORD th32DefaultHeapID; // 进程默认堆ID;    DWORD th32ModuleID; // 进程模块ID;    DWORD cntThreads; // 此进程开启的线程计数;    DWORD th32ParentProcessID;// 父进程ID;    LONG pcPriClassBase; // 线程优先权;    DWORD dwFlags; // 保留;    char szExeFile[MAX_PATH]; // 进程全名;} PROCESSENTRY32;

Process32Next()
函数功能:
获得下一个进程的句柄

BOOLWINAPIProcess32Next(__inHANDLEhSnapshot,__outLPPROCESSENTRY32lppe);

CloseHandle()
函数功能:关闭CreateToolhelp32Snapshot()产生的句柄

BOOL CloseHandle(HANDLE hObject);

详细功能:
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。

关于内核对象,请查看《windows核心编程中》(《windows via c/c++》)相应章节

具体实例代码

DWORD ID;DWORD ProcessID = GetCurrentProcessId();//必要的置位PROCESSENTRY32 pe;memset(&pe, 0x00, sizeof(PROCESSENTRY32));pe.dwSize = sizeof(PROCESSENTRY32);//取全局函数,对于MFC而言,加了是调用WIN API,不加是调用MFC的库HANDLE hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);BOOL result = Process32First(hSnapshot, &pe);while (result){    ID = pe.th32ProcessID;    if (ID == ProcessID)    {        result = Process32Next(hSnapshot, &pe);        continue;    }    //字符串比较,检查记事本程序(notepad.exe)    if (_tcsicmp(pe.szExeFile, _T("notepad.exe")) == 0)    {        MessageBox((NULL), TEXT("找到该进程"), TEXT("tips"), MB_OK);        //打开已存在的进程        HANDLE  Process = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE, pe.th32ProcessID);                ::TerminateProcess(Process, 0);        MessageBox(NULL, TEXT("已杀死该进程"), TEXT("Tips"), MB_OK);        CloseHandle(Process);    }
  1. SendMessage()
  2. PostMessage()

总结:
SendMessage()函数与PostMessage()函数功能类似,都是给窗口发消息,来实现窗口或线程的关闭,难点在与如何抓到窗口,这里介绍个函数FindWindows()

FindWindows()
函数功能:
如果函数执行成功,则返回值是拥有指定窗口类名或窗口名的窗口的句柄。
如果函数执行失败,则返回值为 NULL 。可以通过调用GetLastError函数获得更加详细的错误信息。

HWND FindWindow(    LPCSTR lpClassName,    LPCSTR lpWindowName);

lpClassName
指向一个以null结尾的、用来指定类名的字符串或一个可以确定类名字符串的原子。如果这个参数是一个原子,那么它必须是一个在调用此函数前已经通过GlobalAddAtom函数创建好的全局原子。这个原子(一个16bit的值),必须被放置在lpClassName的低位字节中,lpClassName的高位字节置零。
如果该参数为null时,将会寻找任何与lpWindowName参数匹配的窗口。
lpWindowName
指向一个以null结尾的、用来指定窗口名(即窗口标题)的字符串。如果此参数为NULL,则匹配所有窗口名。

此处的重难点是不知道窗口的类名

解决方案:VS2013在内部整合了一个工具叫做SPY++,用其可以轻易地监测窗口的类名(在所有电脑上窗口类名一致)

具体代码实例

HWND myHwnd = FindWindow(NULL,TEXT("pujifanqiang.txt - 记事本"));if (!myHwnd){    if (!GetProcessId(NULL))        ErrorExit(TEXT("GetProcessId"));}PostMessage(myHwnd, WM_CLOSE, 0, 0);CloseHandle(myHwnd);

但是SendMessage()函数与PostMessage()函数的功能并不仅限制于给窗口发送WM_CLOSE消息,好好使用,必有大用

最后介绍下GetLastError()
函数功能:GetLastError返回的值通过在api函数中调用SetLastError或SetLastErrorEx设置。函数并无必要设置上一次错误信息,所以即使一次GetLastError调用返回的是零值,也不能担保函数已成功执行。只有在函数调用返回一个错误结果时,这个函数指出的错误结果才是有效的。通常,只有在函数返回一个错误结果,而且已知函数会设置GetLastError变量的前提下,才应访问GetLastError;这时能保证获得有效的结果。SetLastError函数主要在对api函数进行模拟的dll函数中使用,所以对vb应用程序来说是没有意义的

DWORD GetLastError(VOID);

可以讲GetLastError()函数整合到MessageBox(),以下代码借鉴于网上其他人答案
具体代码实例

if (!GetProcessId(NULL))    ErrorExit(TEXT("GetProcessId"));
void ErrorExit(LPTSTR lpszFunction){    // Retrieve the system error message for the last-error code    LPVOID lpMsgBuf;    LPVOID lpDisplayBuf;    DWORD dw = GetLastError();    FormatMessage(        FORMAT_MESSAGE_ALLOCATE_BUFFER |        FORMAT_MESSAGE_FROM_SYSTEM |        FORMAT_MESSAGE_IGNORE_INSERTS,        NULL,        dw,        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),        (LPTSTR)&lpMsgBuf,        0, NULL);    // Display the error message and exit the process    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));        //需要头文件<strsafe.h>,该头文件必须在windows.h之后包括        StringCchPrintf((LPTSTR)lpDisplayBuf,        LocalSize(lpDisplayBuf) / sizeof(TCHAR),        TEXT("%s failed with error %d: %s"),        lpszFunction, dw, lpMsgBuf);    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);    LocalFree(lpMsgBuf);    LocalFree(lpDisplayBuf);    ExitProcess(dw);}
0 0
原创粉丝点击