为什么刷新后,找不到句柄了?
可用是什么问题?
好像有时又没问题?var lppe: TProcessEntry32; 
    found : boolean; 
    Hand : THandle;
begin
  Hand := CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
  found := Process32First(Hand,lppe);
//刷新后 found=false
  while found do 
  begin
    ListBox.Items.Add(StrPas(lppe.szExeFile));//列出所有进程。
    found := Process32Next(Hand,lppe); 
  end;
end;

解决方案 »

  1.   

    你的代码在我这儿一直都没有问题啊!
    看看这个也许会有帮助!
    Toolhelp API 简介    Toolhelp APIs是Windows中一组能够方便得到系统中win32应用程序的当前运行状况的函数,这些函数设计目的是实现一些基于Win32子系统的工具,特别是调试器。通过使用Toolhelp API,我们可以实现象Windows附带的系统工具Dr watson一样的功能(当然真正实现它的所有功能不是光靠Toolhelp API一个函数库就可以的)。而且这些函数适用于win9x,winnt,win2k,所以不需要为在不同的windows版本中移植代码操心。  下面将介绍ToolHelp APIs中一些主要的函数和结构。主要有CreateToolhelp32Snapshot和Xxx32First,Xxx32Next系列函数,还有Toolhelp32ReadProcessMemory。所用语言为Object Pascal,对于使用C++的程序员可以参考SDK index中的tool help library [Win32].以下是它们的定义和说明:1. 创建快照函数CreateToolhelp32Snapshotfunction CreateToolhelp32Snapshot(
    dwFlags:DWORD, // 要得到进程的信息,赋为TH32CS_SNAPPROCESS
    // 要得到线程的信息,赋为TH32CS_SNAPTHREAD
    // 要得到指定进程的堆列表,赋为TH32CS_SNAPHEAPLIST
    // 要得到指定进程的模块列表,赋为TH32CS_SNAPMODULE
    th32ProcessID: DWORD // 当我们把dwFlags赋为TH32CS_SNAPMODULE 或者
    // TH32CS_SNAPHEAPLIST时,需要指定具体的进程ID,否则
    // 将忽略此参数。把它赋为0表示当前进程(也就是自己)
    ): THandle; // 返回值THandle将在以后要枚举进程、线程等对象时使用当我们得到快照的句柄后可以分别使用Xxx32First,Xxx32Next这些函数进行对象枚举。它们的定义如下所示:2. Xxx32First,Xxx32Next枚举函数与有关结构l 进程有关的函数与结构
    tagPROCESSENTRY32 = packed record
    dwSize: DWORD; // 指定结构的大小,
    // 在调用Process32First前需要设置,否则将会失败
    cntUsage: DWORD; // 引用计数
    th32ProcessID: DWORD; // 进程号
    th32DefaultHeapID: DWORD; // 进程的堆号,只对Toolhelp函数有意义,并不是一个有效句柄
    th32ModuleID: DWORD; // 进程的模块号,只对Toolhelp函数有意义,并不是一个有效句柄
    cntThreads: DWORD; // 进程中包括的线程数
    th32ParentProcessID: DWORD; // 进程的母进程
    pcPriClassBase: Longint; // 进程的线程的基优先级,所有此进程创建的线程将基于此优先级
    dwFlags: DWORD; // 保留,没有使用
    szExeFile: array[0..MAX_PATH - 1] of Char; // 进程所对应的文件及路径
    end;
    TProcessEntry32 = tagPROCESSENTRY32;function Process32First(
    hSnapshot: THandle; // 前面由CreateToolhelp32Snapshot创建的快照句柄
    var lppe: TProcessEntry32 //函数输出进程信息
    ): BOOL; //调用成功将为True,否则为False
    function Process32Next(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;l 模块有关的函数和结构tagMODULEENTRY32 = record
    dwSize: DWORD; // 指定结构的大小,
    // 在调用Module32First前需要设置,否则将会失败
    th32ModuleID: DWORD; // 模块号
    th32ProcessID: DWORD; // 包含本模块的进程号
    GlblcntUsage: DWORD; // 本模块的全局引用计数
    ProccntUsage: DWORD; // 包含模块的进程上下文中的模块引用计数
    modBaseAddr: PBYTE; // 模块基地址
    modBaseSize: DWORD; // 模块大小(字节数)
    hModule: HMODULE; // 包含模块的进程上下文中的hModule句柄
    // 注意:modBaseAddr 与 hModule 只在th32ProcessID的
    // 上下文才有效
    szModule: array[0..MAX_MODULE_NAME32] of Char; //模块名
    szExePath: array[0..MAX_PATH - 1] of Char; //模块对应的文件名和路径
    end;
    TModuleEntry32 = tagMODULEENTRY32;function Module32First(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL; //同进程说明
    function Module32Next(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL;l 线程有关的函数和结构
    tagTHREADENTRY32 = record
    dwSize: DWORD; // 指定结构的大小,
    // 在调用Thread32First前需要设置,否则将会失败
    cntUsage: DWORD; // 线程引用计数
    th32ThreadID: DWORD; // 线程号
    th32OwnerProcessID: DWORD; // 拥有线程的进程号
    tpBasePri: Longint; // 在线程创建时的初始优先级
    tpDeltaPri: Longint; // 现在线程的优先级的相对于初始值的改变量
    dwFlags: DWORD; // 保留,没有使用
    end;
    TThreadEntry32 = tagTHREADENTRY32;
    function Thread32First(hSnapshot: THandle; var lpte: TThreadEntry32): BOOL; stdcall;
    function Thread32Next(hSnapshot: THandle; var lpte: TThreadENtry32): BOOL; stdcall;l 堆有关的函数和结构
    tagHEAPENTRY32 = record
    dwSize: DWORD; // 指定结构的大小, 
    // 在调用Heap32First前需要设置,否则将会失败
    hHandle: THandle; // 堆的句柄
    dwAddress: DWORD; // 堆起始位置的线性地址
    dwBlockSize: DWORD; // 堆的大小(字节数)
    dwFlags: DWORD; // 标志,为以下值
    // LF32_FIXED 堆内存块的位置是固定的
    // LF32_FREE 堆内存块没有使用
    // LF32_MOVEABLE 堆内存块的位置是可移动的
    dwLockCount: DWORD; // 堆的锁定计数,每次对堆的执行GlobalLock
    // 或者LocalLock都将使它增1
    dwResvd: DWORD; // 保留,没有使用
    th32ProcessID: DWORD; // 拥有本堆的进程号,
    // 这个ID是可以被其他WIN32 API使用的。
    th32HeapID: DWORD; // 堆号,只能在ToolHelp API中内部使用,
    // 并不是有效的句柄
    end;
    THeapEntry32 = tagHEAPENTRY32;function Heap32First(var lphe: THeapEntry32; th32ProcessID, th32HeapID: DWORD): BOOL;
    function Heap32Next(var lphe: THeapEntry32): BOOL;
    3. 更为有用的Toolhelp API函数有Toolhelp32ReadProcessMemory,它可以读其他进程内存空间的内容。function Toolhelp32ReadProcessMemory(
    th32ProcessID: DWORD; // 指定进程
    lpBaseAddress: Pointer; // 要读的进程内存空间的起始地址
    var lpBuffer; // 将要读的内容的保存缓冲区
    cbRead: DWORD; // 要读的字节数
    var lpNumberOfBytesRead: DWORD // 成功读取的字节数
    ): BOOL; // 函数成功返回True,否则返回False下面我通过一个使用Delphi编写的枚举当前系统中的进程的程序来示范具体如何使用Toolhelp APIs.得到其他进程的句柄是很有用的,比如可以清楚知道现在有哪些程序在运行,对于清楚知道系统中应该运行什么程序的用户来说,那些后门程序将暴露无遗。当然Toolhelp API的其他功能主要还是使用在高级应用中。首先我们应该调用CreateToolhelp32Snapshot创建快照;然后调用Process32First,把创建的快照的句柄传递给hSnapshot参数,函数成功返回后我们将在lppe参数中得到第一个进程的信息;继续调用Process32Next,我们将得到后续的进程信息,直到Process32Next返回False为止。记住最后我们应该调用CloseHandle把快照的句柄安全的释放。是不是很简单?下面是范例的源程序,为了简单起见,我只写了关键的语句。uses ... TLHelp32, ... // 需要用到TLHelp32单元即Toolhelp API library.type
    TForm1 = class(TForm)
    ...
    end;var
    Form1: TForm1;
    MyProcess : Tlist; // 返回的进程信息在MyProcess这个TList中。type
    TProcessInfo = Record
    ExeFile : String;
    ProcessID : DWORD;
    end;
    pProcessInfo = ^TProcessInfo;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
    var 
    p : pProcessInfo;
    IsLoopContinue:BOOL;
    FSnapshotHandle:THandle;
    FProcessEntry32:TProcessEntry32; 
    begin
    MyProcess := TList.Create; // 保存进程信息的列表
    MyProcess.Clear; // 初始化列表
    FSnapshotHandle:=
    CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); // 创建系统快照
    FProcessEntry32.dwSize:=Sizeof(FProcessEntry32); // 必须先设置结构的大小
    IsLoopContinue:=
    Process32First(FSnapshotHandle,FProcessEntry32); //得到第一个进程信息
    while integer(IsLoopContinue)<>0 do
    begin
    New(p); 
    p.ExeFile := FProcessEntry32.szExeFile;
    p.ProcessID := FProcessEntry32.th32ProcessID;
    MyProcess.Add(p); // 添加进程信息
    IsLoopContinue:=Process32Next(FSnapshotHandle,FProcessEntry32); // 继续枚举
    end;
    CloseHandle(FSnapshotHandle); // 释放快照句柄 
    end;procedure TForm1.FormDestroy(Sender: TObject);
    var 
    p : pProcessInfo;
    i : integer;
    begin
    With MyProcess do
    for i := Count - 1 DownTo 0 do
    begin 
    p := items[i]; 
    Dispose(p); // 清除动态分配的内存
    Delete(i); // 删除列表中的项
    end;
    end;...end.