进程控制

作者: 307656af5a04 | 来源:发表于2019-07-11 09:07 被阅读15次

    进程控制

    1、获取系统进程

    2、终止当前进程

    3、终止其他进程

    4、保护进程

    5、进程内存空间说明

    6、读进程内存空间

    7、写进程内存空间


    1、获取系统进程

    CreateToolhelp32Snapshot用于获取系统内指定进程的快照

    HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);

    dwFlags指定获取的列表类型

    th32ProcessID进程ID,指定那个进程,当获取系统进程列表或当前进程时取0

    函数执行成功,返回一个快照句柄,否则返回INVALID_HANDLE_VALUE

    | TH32CS_SNAPHEAPLIST | 枚举th32ProcessID参数指定的进程中的堆 |
    | TH32CS_SNAPMODULE | 枚举th32ProcessID参数指定的进程中的模块 |
    | TH32CS_SNAPPROCESS | 枚举系统范围内的进程,此时th32ProcessID被忽略 |
    | TH32CS_SNAPTHREAD | 枚举系统范围内的线程,此时th32ProcessID被忽略 |

    从快照列表中获取进程信息使用Process32First和Process32Next函数,每次调用仅返回一个进程的信息。当不再有剩余信息时,函数返回FALSE.

    BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
    
    BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
    

    LPPROCESSENTRY32 结构体

    typedef struct tagPROCESSENTRY32
    {
        DWORD dwSize;            // 结构体的长度,预先设置
        DWORD cntUsage;            // 进程的引用计数
        DWORD th32ProcessID;        // 进程ID
        ULONG_PTR th32DefaultHeapID;    // 进程默认的堆
        DWORD th32ModuleID;        // 进程模块ID
        DWORD cntThreads;            // 进程创建的线程数
        DWORD th32ParentProcessID;    // 进程的父进程ID
        LONG  pcPriClassBase;        // 进程创建的线程的基本优先级
        DWORD dwFlags;                // 内部使用
        TCHAR szExeFile[MAX_PATH];    // 进程对应可执行文件名 
    }PROCESSENTRY32,*PPROCESSENTRY32;
    

    例子

    #define _AFXDLL
    #include <afx.h>
    #include <TlHelp32.h>  // 声明快照函数的头文件
    
    int main()
    {
        // 使用这个结构体之前,先设置它的大小
        PROCESSENTRY32 pe32; 
    
        // 给系统内的所有进程拍一个快照
        pe32.dwSize = sizeof(pe32);
    
        HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    
        if(hProcessSnap == INVALID_HANDLE_VALUE)
        {
            printf("CreateToolhelp32Snapshot调用失败!\n");
            return -1;
        }
    
        // 遍历快照,轮流显示每个进程的信息
        BOOL bMore = ::Process32First(hProcessSnap,&pe32);
    
        while(bMore)
        {
            printf("进程名称:%s\n",pe32.szExeFile);
            printf("进程ID:%u\n",pe32.th32ProcessID);
            bMore = ::Process32Next(hProcessSnap,&pe32);
        }
    
        // 清除snapshot对象
        ::CloseHandle(hProcessSnap);
    
        system("pause");
        return 0;
    }
    

    ** 2、终止当前进程**

    终止当前进程就是进程如何终止自己的运行。方法有两个

    -- 主线程的入口函数返回,返回时,启动函数调用exit,并将用户的返回值传给它。exit销毁所有全局的和静态的对象,然后调用ExitProcess促使OS终止应用程序。

    -- 程序也可以显式调用ExitProcess,但这样做无法销毁全局的和静态的对象。

    void ExitProcess(UINT uExitCode);

    捕获进程(已结束)退出的代码

    BOOL GetExitCodeProcess(HANDLE hProcess,LPDWORD lpExitCode);

    hProcess[in] Handle to the process

    lpExitCode[in] Pointer to 32-bit variable to receive the process termination status.

    lpExitCode用于装载进程退出代码的一个长整数变量。如进程尚未终止,则取得常数STILL_ACTIVE。

    退出代码也称为进程的返回值,该值存储于进程内核对象中。

    3、终止其他进程

    BOOL TerminateProcess(HANDLE hProcess , DWORD uExitCode);

    hProcess : 指定被终止的进程句柄

    uExitCode : 指定目标进程的退出代码,也可以使用GetExitCodeProcess取得一个进程的退出代码。

    取得进程句柄的两种方法

    -- CreateProcess 会返回进程句柄

    -- 对于一个已存在的进程,首先得到其进程ID,然后使用OpenProcess取得这个进程的访问权限。

    HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);

    dwDesiredAccess:想得到的访问权限,PROCESS_ALL_ACCESS

    bInheritHandle:指定返回句柄是否可被继承

    dwProcessId:指定要打开的进程ID

    返回进程的句柄

    OpenProcess执行失败后返回NULL,这时可进一步调用GetLastError取得错误代码。

    例子

    #include <stdio.h>
    #include <Windows.h>
    
    // 通过进程ID终止进程
    BOOL TerminateProcessFromID(DWORD dwID)
    {
        BOOL bRet = FALSE;
    
        // 打开进程
        HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwID);
    
        if(hProcess !=NULL)
        {
            // 终止进程
            bRet = ::TerminateProcess(hProcess,0);
        }
    
        // 关闭进程句柄
        CloseHandle(hProcess);
    
        return bRet;
    }
    
    // 测试程序
    int main()
    {
        DWORD dwId;
    
        printf("请输入进程号\n");
        scanf("%u",&dwId);
    
        // 通过进程ID终止进程
        if (TerminateProcessFromID(dwId))
        {
            printf("进程终止成功\n");
        }
        else
        {
            printf("进程终止失败\n");
        }
    
        system("pause");
        return 0;
    }
    

    4、进程内存空间说明

    32位OS可寻址4GB的地址空间,也就是OS的虚拟内存空间位4G,win2000开始,64K--2G给应用程序预留,2G--4G为OS预留,0--64K不被映射,目的是为了捕捉程序种的错误。

    每个进程占用的内存空间是离散的,所以要访问进程内存中的一个值,就需要遍历整个64K---2G的地址空间。

    Windows采用分页机制管理内存,每页的大小为4K(X86处理器上),也就是说Windows以4K为单位为应用程序分配内存。

    5、读进程内存空间

    BOOL ReadProcessMemory(HANDLE hProcess , LPCVOID lpBaseAddress , LPVOID lpBuffer , DWORD nSize , LPDWORD lpNumberOfBytesRead);
    hProcess:待读进程句柄
    lpBaseAddress:目标进程待读内存起始地址
    lpBuffer:用来接收读取数据的缓冲区
    nSize:要读取的字节数
    lpNumberOfBytesRead:实际读取的字节数

    6、写进程内存空间

    BOOL WriteProcessMemory(HANDLE hProcess , LPCVOID lpBaseAddress , LPVOID lpBuffer , DWORD nSize , LPDWORD lpNumberOfBytesWritten);
    参数含义与ReadProcessMemory相同
    typedef void* LPVOID
    typedef CONST void* LPCVOID
    typedef DWORD* LPDWORD
    typedef unsigned long DWORD; 32-bit unsigned integer;

    相关文章

      网友评论

        本文标题:进程控制

        本文链接:https://www.haomeiwen.com/subject/xholkctx.html