作者:潘枫  技术交流QQ:598432467 

完整源代码:http://download.csdn.net/source/196884

今天刚注册了CSDN用户,前面在这里学到了很多东西,一直也想自己写点什么,可注册了好多次居然不成功。呵,其它的题外话就不说了,我们今天要谈论的话题是“怎样让自己的程序进程不让别人强行关闭掉”。昨天公司让我写了一个软件,并且不能让别人结束这个程序的进程。前面看到我过一些相关的文章,有创建一个线程不停检测进程名(通过枚举进程列表)的方法,但我觉得这种方法可能有些占资源。还有将自己进程提升为系统进程的,这种我也没有试过,如果谁有这种方法的实现代码给我一份将不甚感激,我今天用到是另外一种方法,拦截API函数,有两种方法:
1.在强行关闭一个进程时系统调用的是
BOOL WINAPI TerminateProcess(
  HANDLE hProcess,
  UINT uExitCode
);
我们如果利用钩子拦截TerminateProcess这个API函数,在系统调用这个函数是先判断是不是我们不让关闭进程的句柄就行了。

2.在调用BOOL WINAPI TerminateProcess(
  HANDLE hProcess,
  UINT uExitCode
);之前系统必须要先用
HANDLE WINAPI OpenProcess(
  DWORD dwDesiredAccess,
  BOOL bInheritHandle,
  DWORD dwProcessId
);在开进程的句柄,如果我们发现第一参数是PROCESS_TERMINATE方式,说明是要强行结束此进程,我们可以这以这种方打开的调用进程分析,看进程ID是不是我们不让关闭的进程的ID,下面我们着重来讲一下这种方法:
因为要用到钩子,所以们先来创建一个DLL工程,创建的过程我在这里就不说了。在这里我使用了windows核心编程里面的APIHOOK类,将这个类拷贝到工程目录下,加入自己的工程。
在DLL工程里加入一个WH_SHELL的钩子,它的作用是进程创建时将DLL文件插入到每一个进程里面,从而达到拦截API函数的目的。

下面是钩子实现部分代码:

//  Defines
#pragma  data_seg(".SHARED")    
    HHOOK     glhHook  =  NULL;  // 安装勾子句柄 
#pragma  data_seg()
#pragma  comment( linker, "/section:shared,rws" )
HINSTANCE glhInstance  =  NULL;  // DLL实例句柄 

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
... {
    glhInstance = (HINSTANCE)hModule;
        return TRUE;
}

static  LRESULT WINAPI ShellHookProc( int  code, WPARAM wParam, LPARAM lParam) 
... {
    return ::CallNextHookEx(glhHook, code, wParam, lParam);
}
extern   " C " __declspec(dllexport) BOOL StartHook(DWORD pid)
... {    
    BOOL bResult=FALSE;
    if(!glhHook)
    ...{
        glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc,glhInstance, 0);
        if(glhHook!=NULL)
        ...{
            bResult=TRUE;
        }
    }
    return bResult; 
}

extern   " C " __declspec(dllexport) BOOL StopHook()
... {    
    BOOL bResult=FALSE;
    if(glhHook)
    ...{
        bResult= UnhookWindowsHookEx(glhHook);
        if(bResult)
        ...{
            glhHook=NULL;
        }
    }
    return bResult;
}

DLL文件插入其它进程里了,下面的工作就是替换OpenProcess函数了,

// ...............................................................................................*/
typedef HANDLE (WINAPI  * PFNOPENPROCESS)(DWORD,BOOL,DWORD);
extern  CAPIHook g_OpenProcess;
//  自定义OpenProcess函数
HANDLE WINAPI Hook_OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
// .............................................................................................../*
HANDLE WINAPI Hook_OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId)
... {
    if(dwDesiredAccess == PROCESS_TERMINATE && dwProcessId == dwProcessId == lpData->dwProcessId/**//*这个值是不让关闭进程的ID*/)
    ...{
        char sz[2048];
        wsprintf(sz, "%d,%d,%d",dwDesiredAccess,dwProcessId,lpData->dwProcessId);
        MessageBox(NULL,sz,"d",MB_OK);
        return NULL;
    }
    
    return ((PFNOPENPROCESS)(PROC)g_OpenProcess)(dwDesiredAccess,bInheritHandle,dwProcessId);
}

// 挂钩OpenProcess函数
CAPIHook g_OpenProcess("kernel32.dll", "OpenProcess",(PROC)Hook_OpenProcess,TRUE);
把上面这代码加入到刚才创建的DLL里就行了。

刚才大家在查看上面代码时看到了lpData->dwProcessId这个参数,这就是我不让关闭的进程ID,那么这个值怎么得到呢。当然方法很多,可以通过窗口名获取窗口句柄

HWND hwnd  =  ::FindWindow(NULL, " 你程序窗口名 " );
DWORD hpid; // 进程ID
GetWindowThreadProcessId( hwnd ,  & hpid );

但如果你的进程没有窗口应该怎么办呢?那么就只能在进程运行时用::GetCurrentProcessId(); 取得,然后通过内存映射的方式传给DLL文件。如下面的代码

typedef  struct  SHWP_STRUCT_  ... {
    DWORD dwProcessId;
    char szModuleFileName[MAX_PATH];
}  SHWP_STRUCT,  * LPSHWP_STRUCT;

// 全局变量定义
HANDLE            hMapping; // 内存映射名柄 
LPSHWP_STRUCT        lpData;  // 共享内存
int  APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                      int        nCmdShow)
... {
    //创建内存共享
    hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,"PCMONITOR."); 
    if(hMapping != NULL) 
    ...{ 
        lpData=(LPSHWP_STRUCT)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0); 
    } 

    lpData->dwProcessId = ::GetCurrentProcessId(); //当前进程ID
    ...............................其它代码 
}DLL里面的内存映射部分代码
// 全局变量定义
HANDLE            hMapping; // 内存映射名柄 
LPSHWP_STRUCT        lpData;  // 共享内存
// ........................................................................../*
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
... {
    //创建内存共享
    hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,"PCMONITOR."); 
    if(hMapping != NULL) 
    ...{ 
        lpData=(LPSHWP_STRUCT)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0); 
    } 
    return TRUE;
}

这样我们的进程在运行时它的进程ID通过lpData->dwProcessId = ::GetCurrentProcessId(); 得到并以内存映射的方式传给DLL文件。
DLL里面拦截了OpenProcess函数里面的DWORD dwProcessId参数,如果这个数据是我们自己进程的ID就直接反回一个NULL值,也就是打开我们进程失败,这样系统就没有办法掉用TerminateProcess强行关闭我们的进程了。如果我们直接拦截TerminateProcess函数,然后不管哪个函数掉用它直接返回TRUE值,那完了,你就永远没想在你机子上强行关闭任何程序,呵,我说的是强行,发送WM_CLOSE消息关了不算哟。

拦截TerminateProcess函数部分代码:

// ...............................................................................................*/
typedef BOOL (WINAPI  * PFNTERMINATEPROCESS)(HANDLE, UINT);
extern  CAPIHook g_TerminateProcess;
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode); //  自定义TerminateProcess函数
// .............................................................................................../*

//  自定义TerminateProcess函数
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode)
... {
    // 取得主模块的文件名称
    char szPathName[MAX_PATH];
    ::GetModuleFileName(NULL, szPathName, MAX_PATH);
    // 构建发送给主窗口的字符串

    char sz[2048];
    wsprintf(sz, "  进程:(%d)%s  进程句柄:%X  退出代码:%d (%x)",::GetCurrentProcessId(), szPathName, hProcess, uExitCode,lpData->dwProcessId);
    MessageBox(NULL,sz,"d",MB_OK);



    return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, uExitCode);
}
//  挂钩TerminateProcess函数
CAPIHook g_TerminateProcess( " kernel32.dll " ,  " TerminateProcess " ,(PROC)Hook_TerminateProcess,TRUE);

怎样让自己的程序进程不让别人强行关闭掉相关推荐

  1. 怎么彻底关闭计算机应用程序,电脑自动关机前如何强行关闭应用程序

    加上-f Windows XP的关机是由Shutdown.exe程序来控制的,位于Windows\System32文件夹中.如果想让Windows 2000也实现同样的效果,可以把Shutdown.e ...

  2. 关闭msmpeng_你知道吗?把电脑系统里的这些进程关闭掉,可以提升系统流畅

    在使用电脑的时候,很多用户都有感觉到,电脑刚开启使用的时候,win系统运行还是很流畅的.运行了一段时间后,就会感觉win系统慢慢的卡顿起来. 主要原因是因为,我们在使用电脑的时候会运行很多软件,在关闭 ...

  3. Android应用程序进程启动过程的源代码分析(1)

    Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实 ...

  4. python 关闭exe程序进程

    python 关闭exe程序进程 import os def kill_exe(exe_name):"""杀死exe进程:param exe_name:进程名字:retu ...

  5. 应用程序进程(一):创建应用程序

    1.ActivityManagerService发送创建请求 startViaZygote函数通过函数zygoteSendArgsAndGetResult()调用Zygote进程创建一个指定的应用程序 ...

  6. 【Linux 内核】进程管理 ( 进程与操作系统 | 进程与程序 | 进程与线程 | 虚拟地址空间 )

    文章目录 一.进程与操作系统 二.进程与程序 三.进程与线程 四.虚拟地址空间 一.进程与操作系统 操作系统与硬件的关系 : 操作系统 使用 硬件 提供的资源 , 如 CPU , 内存 , 磁盘 , ...

  7. c语言设置程序自动执行,c语言如何设置程序进程执行优先权

    c语言如何设置程序进程执行优先权 使用setpriority()函数设置程序进程执行优先权: 头文件: #include#include 定义函数: int setpriority(int which ...

  8. Android应用程序进程启动过程

    相关文章 Android系统架构与系统源码目录 Android系统启动流程(一)解析init进程启动过程 Android系统启动流程(二)解析Zygote进程启动过程 Android系统启动流程(三) ...

  9. C# 强制关闭当前程序进程(完全Kill掉不留痕迹)

    C# 强制关闭当前程序进程(完全Kill掉不留痕迹) 原文:C# 强制关闭当前程序进程(完全Kill掉不留痕迹) C# 强制关闭当前程序进程(完全Kill掉不留痕迹) C#代码 /// <sum ...

最新文章

  1. VSCode 安装 Go 插件、gopls 是个什么东东
  2. 科普:浅谈 Hellinger Distance
  3. QTP简单框架(6)之脚本编写实例
  4. Tengine-Ngnix高级版
  5. 接口中的默认方法和静态方法
  6. Leetcode--19. 删除链表的倒数第N个节点
  7. 信息学奥赛一本通C++语言——1010:计算分数的浮点数值
  8. 软件驱动安装在docker_低成本的无线打印:群晖上通过Docker容器实现Airprint
  9. 区块链学习笔记:DAY01 区块链的技术原理
  10. 如何手动启动消防广播_怎样启动消防应急广播及求救系统?
  11. java中的装箱和拆箱
  12. 银河麒麟系统服务端命令_麒麟系统介绍
  13. 【数据库】E-R图相关知识、绘制方法及工具推荐
  14. 可以获得高排名的B2B平台大全
  15. 校园网页设计成品 学校班级网页制作模板 大学生静态HTML网页源码 dreamweaver网页作业 简单网页课程成品
  16. AI实战:目标检测模型应用之生活垃圾图片分类
  17. 学法减分拍照识题小程序开发
  18. Cadence Allegro 如何添加Artwork光绘底片文件?
  19. iOS中调用短信、电话、邮件、Safari浏览器API
  20. 李宏毅-机器学习-RNN-笔记

热门文章

  1. word2007中的表格内的内容怎么上标
  2. 初识 Scrapy - Feed导出
  3. OpenWRT的Feeds分析学习
  4. 如何去除discuz X2论坛网址中的forum.php
  5. 放弃哪吒造车增资,360的“智能汽车网络安全”牌不好打
  6. 在springboot遇到的 Access denied for user ‘***‘@‘localhost‘ (using password: YES)问题
  7. Unity3D 材质丢失
  8. html图片环绕文字,CSS_如何让文字环绕图片显示?
  9. 做数据分析,软件工具少不了,好用的数据分析软件工具
  10. 早产儿发育迟缓怎么办