You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CreateToolhelp32Snapshot和Python ctypes枚举线程?代码为何输出0?

问题分析与修复

你的代码始终打印0的原因主要有两点:

1. 未检查快照创建是否成功

CreateToolhelp32Snapshot调用可能因权限不足、目标进程不存在等原因失败,返回INVALID_HANDLE_VALUE无效句柄。此时调用Thread32First会导致结构体未被正确填充,th32ThreadID保持初始的0值;如果函数因类型不匹配等问题错误返回True,就会打印出0。

2. 未过滤目标进程的线程

使用TH32CS_SNAPTHREAD标志创建的快照会包含系统中所有线程,Thread32First返回的第一个线程大概率不属于目标进程,你需要手动筛选th32OwnerProcessID与目标PID一致的线程。

另外,代码还存在资源泄漏问题:未调用CloseHandle释放快照句柄。


修复后的代码

import ctypes
from ctypes import wintypes

pid = 1234
TH32CS_SNAPTHREAD = 0x00000004
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

class THREADENTRY32(ctypes.Structure):
    _fields_ = [
        ('dwSize',             wintypes.DWORD),
        ('cntUsage',           wintypes.DWORD),
        ('th32ThreadID',       wintypes.DWORD),
        ('th32OwnerProcessID', wintypes.DWORD),
        ('tpBasePri',          wintypes.LONG),
        ('tpDeltaPri',         wintypes.LONG),
        ('dwFlags',            wintypes.DWORD)
    ]

# 定义函数参数和返回值类型
CreateToolhelp32Snapshot = kernel32.CreateToolhelp32Snapshot
CreateToolhelp32Snapshot.argtypes = (wintypes.DWORD, wintypes.DWORD)
CreateToolhelp32Snapshot.restype = wintypes.HANDLE

Thread32First = kernel32.Thread32First
Thread32First.argtypes = (wintypes.HANDLE, ctypes.POINTER(THREADENTRY32))
Thread32First.restype = wintypes.BOOL

Thread32Next = kernel32.Thread32Next
Thread32Next.argtypes = (wintypes.HANDLE, ctypes.POINTER(THREADENTRY32))
Thread32Next.restype = wintypes.BOOL

CloseHandle = kernel32.CloseHandle
CloseHandle.argtypes = (wintypes.HANDLE,)
CloseHandle.restype = wintypes.BOOL

# 创建线程快照
h_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pid)
if h_snapshot == INVALID_HANDLE_VALUE:
    print(f"创建快照失败,错误码: {ctypes.get_last_error()}")
else:
    thread_entry = THREADENTRY32()
    thread_entry.dwSize = ctypes.sizeof(THREADENTRY32)
    
    # 枚举线程并过滤目标进程
    if Thread32First(h_snapshot, ctypes.byref(thread_entry)):
        found = False
        while True:
            if thread_entry.th32OwnerProcessID == pid:
                print(f"找到目标进程的线程ID: {thread_entry.th32ThreadID}")
                found = True
                break
            if not Thread32Next(h_snapshot, ctypes.byref(thread_entry)):
                break
        if not found:
            print("未找到目标进程的线程")
    else:
        print(f"枚举线程失败,错误码: {ctypes.get_last_error()}")
    
    # 释放快照句柄
    CloseHandle(h_snapshot)

内容的提问来源于stack exchange,提问作者Utkonos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:54:56