C/C++ Windows API——线程挂起、唤醒与终止

// ThreadDemo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>//GetModuleFileNameEx

int main()
{
    BOOL ret;
    DWORD dwFlags = TH32CS_SNAPTHREAD;
    HANDLE snapshotHandle = CreateToolhelp32Snapshot(dwFlags, 0);
    if (snapshotHandle == NULL || snapshotHandle == INVALID_HANDLE_VALUE) {
        printf("CreateToolhelp32Snapshot -> processHandle=%p(NULL or INVALID_HANDLE_VALUE) -> fail(%ld)\n", snapshotHandle, GetLastError());
    }
    else {
        printf("CreateToolhelp32Snapshot -> processHandle=%p -> succ\n", snapshotHandle);

        /*
        typedef struct tagTHREADENTRY32 {
        DWORD   dwSize;             //指定结构的长度,以字节为单位。如果你不初始化的dwSizeThread32First将调用失败。
        DWORD   cntUsage;           //deprecated, always zero
        DWORD   th32ThreadID;       // this thread
        DWORD   th32OwnerProcessID; // Process this thread is associated with
        LONG    tpBasePri;          //线程在内核中分配的优先级,tpBasePri值为0到31, 0为最低优先级,更多的信息请看KeQueryPriorityThread
        LONG    tpDeltaPri;         //deprecated, always zero
        DWORD   dwFlags;            //deprecated, always zero
        } THREADENTRY32;
        */
        THREADENTRY32 threadEntry32 = { 0 };
        threadEntry32.dwSize = sizeof(THREADENTRY32);
        /*
        BOOL WINAPI Thread32First(
        HANDLE hSnapshot,
        LPTHREADENTRY32 lpte
        );
        */
        BOOL hasNext = Thread32First(snapshotHandle, &threadEntry32);
        if (!hasNext) {
            printf("Thread32First processHandle=%p -> fail(%ld)\n", snapshotHandle, GetLastError());
        }
        while (hasNext) {
            printf("Thread32Next -> th32ThreadID=%ld, th32OwnerProcessID=%ld, tpBasePri=%ld -> succ\n", threadEntry32.th32ThreadID, threadEntry32.th32OwnerProcessID, threadEntry32.tpBasePri);

            /*
            WINBASEAPI HANDLE WINAPI OpenProcess(
            _In_ DWORD dwDesiredAccess,
            _In_ BOOL bInheritHandle,
            _In_ DWORD dwProcessId
            );

            #define PROCESS_TERMINATE                  (0x0001)
            #define PROCESS_CREATE_THREAD              (0x0002)
            #define PROCESS_SET_SESSIONID              (0x0004)
            #define PROCESS_VM_OPERATION               (0x0008)
            #define PROCESS_VM_READ                    (0x0010)
            #define PROCESS_VM_WRITE                   (0x0020)
            #define PROCESS_DUP_HANDLE                 (0x0040)
            #define PROCESS_CREATE_PROCESS             (0x0080)
            #define PROCESS_SET_QUOTA                  (0x0100)
            #define PROCESS_SET_INFORMATION            (0x0200)
            #define PROCESS_QUERY_INFORMATION          (0x0400)
            #define PROCESS_SUSPEND_RESUME             (0x0800)
            #define PROCESS_QUERY_LIMITED_INFORMATION  (0x1000)
            #define PROCESS_SET_LIMITED_INFORMATION    (0x2000)
            #if (NTDDI_VERSION >= NTDDI_VISTA)
            #define PROCESS_ALL_ACCESS        (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ 0xFFFF)
            #else
            #define PROCESS_ALL_ACCESS        (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ 0xFFF)
            #endif
            */
            DWORD dwProcessDesiredAccess = PROCESS_ALL_ACCESS;
            BOOL bInheritHandle = FALSE;
            DWORD dwProcessID = threadEntry32.th32OwnerProcessID;
            HANDLE processHandle = OpenProcess(dwProcessDesiredAccess, bInheritHandle, dwProcessID);
            if (processHandle == NULL || processHandle == INVALID_HANDLE_VALUE) {
                printf("OpenProcess dwProcessID=%ld -> processHandle=%p(NULL or INVALID_HANDLE_VALUE) -> fail(%ld)\n", dwProcessID, processHandle, GetLastError());
            }
            else {
                printf("OpenProcess dwProcessID=%ld -> processHandle=%p -> succ\n", dwProcessID, processHandle);

                /*
                _Success_(return != 0)
                _Ret_range_(1, nSize)
                DWORD WINAPI GetModuleFileNameExW(
                    _In_opt_ HANDLE hProcess,
                    _In_opt_ HMODULE hModule,
                    _When_(return < nSize, _Out_writes_to_(nSize, return + 1))
                    _When_(return == nSize, _Out_writes_all_(nSize))
                    LPTSTR lpFilename,
                    _In_ DWORD nSize
                );

                If the function succeeds, the return value specifies the length of the string copied to the buffer.
                If the function fails, the return value is zero. To get extended error information, call GetLastError.
                */
                HMODULE hModule = NULL;
                const DWORD nSize = MAX_PATH;
                TCHAR lpFilename[nSize];
                DWORD dwRet = GetModuleFileNameEx(processHandle, hModule, lpFilename, nSize);
                if (dwRet == 0) {
                    printf("GetModuleFileNameEx processHandle=%p -> fail(%ld)\n", processHandle, GetLastError());
                }
                else {
                    _tprintf(_T("GetModuleFileNameEx processHandle=%p -> fileName=%s\n"), processHandle, lpFilename);
                }

                if (_tcsstr(lpFilename, _T("notepad.exe"))) {
                    /*
                    WINBASEAPI _Ret_maybenull_ HANDLE WINAPI OpenThread(
                    _In_ DWORD dwDesiredAccess,
                    _In_ BOOL bInheritHandle,
                    _In_ DWORD dwThreadId
                    );

                    dwDesiredAccess可以是如下值(OpenThread和OpenProcess类似)
                    #define THREAD_TERMINATE                 (0x0001)
                    #define THREAD_SUSPEND_RESUME            (0x0002)
                    #define THREAD_GET_CONTEXT               (0x0008)
                    #define THREAD_SET_CONTEXT               (0x0010)
                    #define THREAD_QUERY_INFORMATION         (0x0040)
                    #define THREAD_SET_INFORMATION           (0x0020)
                    #define THREAD_SET_THREAD_TOKEN          (0x0080)
                    #define THREAD_IMPERSONATE               (0x0100)
                    #define THREAD_DIRECT_IMPERSONATION      (0x0200)
                    // begin_wdm
                    #define THREAD_SET_LIMITED_INFORMATION   (0x0400)  // winnt
                    #define THREAD_QUERY_LIMITED_INFORMATION (0x0800)  // winnt
                    #define THREAD_RESUME                    (0x1000)  // winnt
                    #if (NTDDI_VERSION >= NTDDI_VISTA)
                    #define THREAD_ALL_ACCESS         (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ 0xFFFF)
                    #else
                    #define THREAD_ALL_ACCESS         (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ 0x3FF)
                    #endif
                    */
                    DWORD dwDesiredAccess = THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION;
                    BOOL bInheritHandle = FALSE;
                    DWORD dwThreadId = threadEntry32.th32ThreadID;
                    //打开句柄后都要记得关闭
                    HANDLE threadHandle = OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId);
                    if (threadHandle == NULL || threadHandle == INVALID_HANDLE_VALUE) {
                        printf("OpenThread dwThreadId=%ld -> threadHandle=%p(NULL or INVALID_HANDLE_VALUE) -> fail(%ld)\n", dwThreadId, threadHandle, GetLastError());
                    }
                    else {
                        printf("OpenThread -> threadHandle=%p -> succ\n", threadHandle);
                        /*
                        WINBASEAPI DWORD WINAPI SuspendThread(
                        _In_ HANDLE hThread
                        );

                        If the function succeeds, the return value is the thread's previous suspend count;
                        otherwise, it is (DWORD) -1. To get extended error information, use the GetLastError function.
                        */
                        DWORD preSuspendCnt = SuspendThread(threadHandle);
                        if (preSuspendCnt == -1) {
                            printf("SuspendThread -> fail(%ld)\n", GetLastError());
                        }
                        else {
                            printf("SuspendThread -> preSuspendCnt=%d -> succ\n", preSuspendCnt);
                        }

                        /*
                        WINBASEAPI DWORD WINAPI ResumeThread(
                        _In_ HANDLE hThread
                        );

                        If the function succeeds, the return value is the thread's previous suspend count.
                        If the function fails, the return value is (DWORD) -1. To get extended error information, call GetLastError.
                        */
                        preSuspendCnt = ResumeThread(threadHandle);
                        if (preSuspendCnt == -1) {
                            printf("ResumeThread -> fail(%ld)\n", GetLastError());
                        }
                        else {
                            printf("ResumeThread -> preSuspendCnt=%d -> succ\n", preSuspendCnt);
                        }
                        /*
                        WINBASEAPI BOOL WINAPI TerminateThread(
                        _In_ HANDLE hThread,
                        _In_ DWORD dwExitCode
                        );
                        */
                        ret = TerminateThread(threadHandle, 0);
                        if (ret) {
                            printf("TerminateThread -> succ\n");
                        }
                        else {
                            printf("TerminateThread -> fail(%ld)\n", GetLastError());
                        }

                        ret = CloseHandle(threadHandle);
                        if (ret) {
                            printf("CloseHandle thread -> ret=%d\n", ret);
                        }
                        else {
                            printf("CloseHandle thread -> ret=%d -> fail(%ld)\n", ret, GetLastError());
                        }
                    }
                }
                CloseHandle(processHandle);
            }
            hasNext = Thread32Next(snapshotHandle, &threadEntry32);
            if (!hasNext) {
                //遍历完线程的时候Thread32Next会设置错误码10,为环境错误
                printf("Thread32Next handle=%p -> fail(%ld)\n", snapshotHandle, GetLastError());
            }
        }
        ret = CloseHandle(snapshotHandle);
    }

    system("pause");
    return 0;
}

这里写图片描述

1. 创建一个基于对话框的应用程序。并增加如图所示控件;分别为3个进度条控件关联三个进度条类型的变量;并在对话框的初始化函数中,设定进度条的范围;为编辑框关联一个整型的变量;为12个按钮添加消息处理函数; 2. 定义结构体:用做线程函数的参数传递 typedef struct Threadinfo{ CProgressCtrl *progress;//进度条对象 int speed; //进度条速度 int pos; //进度条位置 } thread,*lpthread; 3. 为对话框增加三个句柄,用于标识各个线程; HANDLE hThread1; //线程1线程句柄 HANDLE hThread2; //线程2线程句柄 HANDLE hThread3; //线程3线程句柄 在增加三个结构体类型的变量,用做线程函数的参数传递; HANDLE hThread1; //线程1线程句柄 HANDLE hThread2; //线程2线程句柄 HANDLE hThread3; //线程3线程句柄 4. 新增一个静态的全局变量,用于记录所有线程的状态:static int GlobalVar=10000; 5. 声明并编写线程函数,注意只能有一个参数,且函数的返回值类型也是固定的;函数名可以自定义; DWORD WINAPI ThreadFun(LPVOID pthread);//线程入口函数 6. 在启动按钮的消息处理函数中编写如下代码: thread1.progress=&m_progress1;//进度条对象 thread1.speed=100;//速度 thread1.pos=0;//初始位置 hThread1=CreateThread(NULL,0,ThreadFun,&thread1;,0,0);//创建并开始线程 if (!hThread1) { MessageBox("创建线程失败"); } 7. 编写线程函数(一般是一个死循环,或者需要花费时间很长的算法!否者就失去了多线程的意义) DWORD WINAPI ThreadFun(LPVOID pthread) //线程入口函数 { lpthread temp=(lpthread)pthread;//参数强制转换为结构体类型 temp->progress->SetPos(temp->pos); //设置被传递过来的进度条的位置 while(temp->posspeed); /设置速度 temp->pos++; //增加进度 temp->progress->SetPos(temp->pos); //设置进度条的新位置 GlobalVar--; if(temp->pos==20) { temp->pos=0; //进度条满则归0 } } return true; } 8. 在挂起按钮函数中,编写如下代码: if(SuspendThread(hThread1)==0xFFFFFFFF) { MessageBox("挂起失败!进程可能已经死亡或未创建!"); return; } 9. 在执行按钮函数中,编写如下代码: if(ResumeThread(hThread1)==0xFFFFFFFF) { MessageBox("执行失败!进程可能已经死亡或未创建!"); return; } 10. 在停止按钮函数中,编写如下代码: if(TerminateThread(hThread1,0))//前些终止线程 { CloseHandle(hThread1);//销毁线程句柄 } else { MessageBox("终止进程失败!"); } 11. 为应用程序添加WM_TIMER消息,实时更新全局变量的值到编辑框;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值