通常如果已知一个窗体的名称,可以用Findwindow找到窗体句柄,再用Getwindows遍历窗体上控件,找到控件句柄.
这只是理想状态,有时弹出模式对话框根本就没有标题,从SPY++上就可以看出有很多是这种情况.我从SPY++上也看到可以通过进程的句柄,或线程的句柄下找到这些控件,网上多是遍历进程 和线程的文章,我已找到了进程或线程的句柄,如何遍历这进程或线程下的控件找到我需要的控件的句柄,一直没有成功,急请各位大侠指点.顿足拜谢.
注:所找到的进程是别的程序创建的,我不知代码的.
<img src="c:\u1.jpg" alt="0" />

枚举线程的窗口
EnumThreadWindows

引用 1 楼 jacknes009 的回复:
http://jacknes009.blog.163.com/blog/static/2810542320075275498380/

我已找到了所有的进程,没有必要再枚举进程得到进程的名字了.我需要的是进程下各控件的句柄

引用 2 楼 akirya 的回复:
枚举线程的窗口
EnumThreadWindows

不是要枚举线程的窗口,线程的句柄都已得到了,我要的是线程下各控件的句柄.

这个就不怎么懂了,帮顶下吧,
等待结果~~~

<img src="c:\u1.jpg" alt="0" />
file:///d:/sss.jpg

比较汗….

引用 4 楼 nihongsheng 的回复:
引用 2 楼 akirya 的回复:
枚举线程的窗口
EnumThreadWindows

不是要枚举线程的窗口,线程的句柄都已得到了,我要的是线程下各控件的句柄.


枚举线程的窗口就是为了得到线程下各控件的句柄啊,楼主想要的不是线程下所有控件的句柄列表吗?

引用 7 楼 Waiting4you 的回复:
引用 4 楼 nihongsheng 的回复:
引用 2 楼 akirya 的回复:
枚举线程的窗口
EnumThreadWindows

不是要枚举线程的窗口,线程的句柄都已得到了,我要的是线程下各控件的句柄.

枚举线程的窗口就是为了得到线程下各控件的句柄啊,楼主想要的不是线程下所有控件的句柄列表吗?

我已枚举出了线程的窗口,得到的是线程的句柄,再往下如何得到线程下所有控件的句柄列表就不行了.
有一篇文章是用EnumThreadWindows 获得线程句柄的例子,我添附在下面.这个例子是用VB写的,我把它拷到VB
里面,实际运行了一下,得不到线程下控件列表的句柄.您可以试试.
我现在在想别的办法:遍历所有标题为空的对话框,再从对话框中查找所需要的控件(条件是这个控件的标题在内存中是唯一的),如果找到的话,再找其父窗口的句柄来发消息.目前在试写中.成功以后贴上与大家共享.
如何得到线程下所有控件的列表,应用何函数?能否说得说细一点或贴上代码让大伙瞄瞄.已经搞了三天了,实在走投无路了万分焦急.

添附:
      如何使用 WIN32 API 枚举窗口
          1.在 Visual Basic 中启动一个新的项目。默认情况下创建 Form1。
            2.添加两个 CommandButtons 和一个 TextBox。
            3.将下面的代码复制到该窗体的模块中:      Option Explicit

      Private Sub Command1_Click()
        Dim lRet As Long, lParam As Long
        Dim lhWnd As Long

        lhWnd = Me.hwnd  ' Find the Form's Child Windows
        ' Comment the line above and uncomment the line below to
        ' enumerate Windows for the DeskTop rather than for the Form
        'lhWnd = GetDesktopWindow()  ' Find the Desktop's Child Windows
        ' enumerate the list
        lRet = EnumChildWindows(lhWnd, AddressOf EnumChildProc, lParam)
      End Sub

      Private Sub Command2_Click()
        Dim lRet As Long
        Dim lParam As Long

        'enumerate the list
        lRet = EnumWindows(AddressOf EnumWinProc, lParam)
        ' How many Windows did we find?
        Debug.Print TopCount; " Total Top level Windows"
        Debug.Print ChildCount; " Total Child Windows"
        Debug.Print ThreadCount; " Total Thread Windows"
        Debug.Print "For a grand total of "; TopCount + _
        ChildCount + ThreadCount; " Windows!"
      End Sub

            4.添加包含以下代码的模块:      Option Explicit

      Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
      End Type

      Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
        lpRect As RECT) As Long

      Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, _
        ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
        ByVal nHeight As Long, ByVal bRepaint As Long) As Long

      Declare Function GetDesktopWindow Lib "user32" () As Long

      Declare Function EnumWindows Lib "user32" _
        (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

      Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _
        As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

      Declare Function EnumThreadWindows Lib "user32" (ByVal dwThreadId _
        As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long

      Declare Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As Long, lpdwProcessId As Long) As Long

      Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
        (ByVal hwnd As Long, ByVal lpClassName As String, _
        ByVal nMaxCount As Long) As Long

      Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
        (ByVal hwnd As Long, ByVal lpString As String, _
        ByVal cch As Long) As Long

      Public TopCount As Integer    ' Number of Top level Windows
      Public ChildCount As Integer  ' Number of Child Windows
      Public ThreadCount As Integer  ' Number of Thread Windows

      Function EnumWinProc(ByVal lhWnd As Long, ByVal lParam As Long) _
        As Long
        Dim RetVal As Long, ProcessID As Long, ThreadID As Long
        Dim WinClassBuf As String * 255, WinTitleBuf As String * 255
        Dim WinClass As String, WinTitle As String

        RetVal = GetClassName(lhWnd, WinClassBuf, 255)
        WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces
        RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)
        WinTitle = StripNulls(WinTitleBuf)
        TopCount = TopCount + 1
        ' see the Windows Class and Title for each top level Window
        Debug.Print "Top level Class = "; WinClass; ", Title = "; WinTitle
        ' Usually either enumerate Child or Thread Windows, not both.
        ' In this example, EnumThreadWindows may produce a very long list!
        RetVal = EnumChildWindows(lhWnd, AddressOf EnumChildProc, lParam)
        ThreadID = GetWindowThreadProcessId(lhWnd, ProcessID)
        RetVal = EnumThreadWindows(ThreadID, AddressOf EnumThreadProc, _
        lParam)
        EnumWinProc = True
      End Function

      Function EnumChildProc(ByVal lhWnd As Long, ByVal lParam As Long) _
        As Long
        Dim RetVal As Long
        Dim WinClassBuf As String * 255, WinTitleBuf As String * 255
        Dim WinClass As String, WinTitle As String
        Dim WinRect As RECT
        Dim WinWidth As Long, WinHeight As Long

        RetVal = GetClassName(lhWnd, WinClassBuf, 255)
        WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces
        RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)
        WinTitle = StripNulls(WinTitleBuf)
        ChildCount = ChildCount + 1
        ' see the Windows Class and Title for each Child Window enumerated
        Debug.Print "  Child Class = "; WinClass; ", Title = "; WinTitle
        ' You can find any type of Window by searching for its WinClass
        If WinClass = "ThunderTextBox" Then    ' TextBox Window
            RetVal = GetWindowRect(lhWnd, WinRect)  ' get current size
            WinWidth = WinRect.Right - WinRect.Left ' keep current width
            WinHeight = (WinRect.Bottom - WinRect.Top) * 2 ' double height
            RetVal = MoveWindow(lhWnd, 0, 0, WinWidth, WinHeight, True)
            EnumChildProc = False
        Else
            EnumChildProc = True
        End If
      End Function

      Function EnumThreadProc(ByVal lhWnd As Long, ByVal lParam As Long) _
        As Long
        Dim RetVal As Long
        Dim WinClassBuf As String * 255, WinTitleBuf As String * 255
        Dim WinClass As String, WinTitle As String

        RetVal = GetClassName(lhWnd, WinClassBuf, 255)
        WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces
        RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)
        WinTitle = StripNulls(WinTitleBuf)
        ThreadCount = ThreadCount + 1
        ' see the Windows Class and Title for top level Window
        Debug.Print "Thread Window Class = "; WinClass; ", Title = "; _
        WinTitle
        EnumThreadProc = True
      End Function

      Public Function StripNulls(OriginalStr As String) As String
        ' This removes the extra Nulls so String comparisons will work
        If (InStr(OriginalStr, Chr(0)) > 0) Then
            OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
        End If
        StripNulls = OriginalStr
      End Function

            5.运行项目并单击 Command1。这将枚举出该窗体的子窗口直至找到 TextBox,然后将 TextBox
            的高度扩大一倍并将其移动到位置 (0, 0)(该窗体的左上方。)
            6.单击
            Command2。这会立即在即时窗口中列出所有顶级窗口及其子窗口以及与其线程关联的任何非子窗口的类和标题(如果存在)。请注意,这可以是一个非常长的列表,可能需要一段时间才能列出所有内容。

            7.从“运行”菜单选择“结束”或单击“结束”按钮以停止程序。根据注释更改 Sub Command1_Click 中的代码以传递来自
            GetDesktopWindow 的句柄。运行项目并单击 Command1 以枚举 DeskTop
            的所有子窗口。请注意,完成此过程需要花费一些时间。

引用 6 楼 loveshell 的回复:
<img src="c:\u1.jpg" alt="0" />
file:///d:/sss.jpg

比较汗….


如何贴上图片,屡次都不成功

先把图片传到晚上,然后点编辑框上面的插入图片就可以了。

控件也是有窗口的,枚举窗口为什么不能枚举的控件的?

咳,不知道是不是我理解错了,EnumThreadWindows列举的是窗口句柄而不是线程句柄!
下面是用EnumThreadWindows列举出本线程所有窗口的例子(所有窗口的标题放在Form1的Memo1里),如果楼主还要找这些窗口里的子控件,可以再用FindWindowEx或EnumChildWindows之类的方法找。

C/C++ code
BOOL CALLBACK EnumThreadWndProc( HWND hwnd, LPARAM lParam ) { char buf[100]={0}; ::SendMessage(hwnd,WM_GETTEXT,100,(WPARAM)buf); // 这里的hwnd就是EnumThreadWindows找到的窗口HWND ((TMemo*)lParam)->Lines->Add(buf); return TRUE; } void __fastcall TForm1::Button1Click(TObject *Sender) { EnumThreadWindows( GetCurrentThreadId() ,(WNDENUMPROC)EnumThreadWndProc, LPARAM(Memo1)); } //—————————————————————————

引用 10 楼 loveshell 的回复:
先把图片传到晚上,然后点编辑框上面的插入图片就可以了。

控件也是有窗口的,枚举窗口为什么不能枚举的控件的?


图片传到网上什么地方,能指示下?

这里控件是放在一个模式对话框里,标题栏是空的字符串,表面上看到的标题栏是一个Edit控件.而系统中存在大量"#32770"的对话框,它们的标题也各种各样,很可能就有空字符串,而它返回的是找到的第一个窗口的句柄,不能保证一定是你需要的.所以较为可行的方法是枚举系统当前的所有进程,从中查找模块名为您需要的进程,从进程中查找属于控件的句柄.
现在网上枚举窗口的方法绝大多数都是从一个对话框里找它上面控件的句柄,我因为这个对话框的句柄找不到,才想用进程或线程里找.
你把SPY++打开,调到查看线程或进程里,可以看到线程下面控件名及句柄.我想知道它是怎么出来的.
请告诉我传图片的方法,我上传一张图片给您瞧瞧

引用 10 楼 loveshell 的回复:]
先把图片传到晚上,然后点编辑框上面的插入图片就可以了。

控件也是有窗口的,枚举窗口为什么不能枚举的控件的?
[/Quote]

凭印象写的,没调试过。。。

C/C++ code
HANDLE GetMyHandle(HANDLE hParant)// 参数为父句柄 { const int nBufLen = 256; char cTemp[nBufLen]; HANDLE hTemp; hTemp = GetWindow(hParant,GW_CHILD);//获得进程下的第一个子句柄 while(hTemp) { memset(cTemp,0,nBufLen); GetWindowText(hTemp,cTemp,nBufLen); if (AnsiString(cTemp) == "AfxFrameOrView42") return hTemp;// 若是要找的句柄则返回 hTemp = GetWindow(hTemp,GW_HWNDNEXT); } return NULL; }

引用 14 楼 Jikycc 的回复:
凭印象写的,没调试过。。。
C/C++ code
HANDLE  GetMyHandle(HANDLE hParant)// 参数为父句柄
{
    const int nBufLen = 256;
    char cTemp[nBufLen];
 
    HANDLE hTemp;
    hTemp = GetWindow(hParant,GW_CHILD);//获得进程下的第一个子句柄
    while(hTemp)
    {
    memset(cTemp,0,nBufLen);
        GetWindowText(hTemp,cTemp,nBufLen);

    if (AnsiString(cTemp) == "AfxFrameOrView42"…

谢谢指点.但我认为进程下面的子句柄是线程,线程下面才是控件,从13楼我贴出的图片上可以看出.
画有二个齿轮的是进程,一个齿轮的是线程,再下面是各控件.可能你的办法也只能找到线程了.
我原也想这么干,我认为对话框是控件的容器,所以能用GetWindow(hParant,GW_CHILD)方法找,线程与控件可能不存在这个关系,所以能否用这个函数找我不敢确定.
昨天通过努力我用下列办法写的代码:
遍历所有标题为空的对话框,再从对话框中查找所需要的控件(条件是这个控件的标题在内存中是唯一的)
调试后虽然还有BUG,但一般情况下可以找到所需的控件句柄,有时找的不大对或找不到.但不是通过线程与进程来找的,故与我本意有差别,供参考指正
HWND TForm1::FindPressmeBtnHandleProcess()
{
  HWND h_WindowHandle= FindWindow("#32770","");    //Empty caption Dialogbox handle
  HWND h_ControHandle;          //Control handle
  char cFindControCaption[128];
  char Searchnt[128];
  char cFindClassName[128];

  while(h_WindowHandle)
  {
        sPush(h_WindowHandle);
GetcFindClassName(h_WindowHandle,cFindClassName,128);
SendMessage(h_WindowHandle,WM_GETTEXT,128,(LPARAM)Searchnt);
if  (AnsiString(cFindClassName)== "#32770" && AnsiString( Searchnt)=="")
  {
h_ControHandle=GetWindow(h_WindowHandle,GW_CHILD);
while(1)
{
SendMessage(h_ControHandle,WM_GETTEXT,128,(LPARAM)FindControCaption);
GetcFindClassName(h_ControHandle,cFindClassName,128);
  if (AnsiString(cFindControCaption)=="Press me" && AnsiString(FindClassName)== "Button" )
{
                                //Find the handle and stop the loop
return h_ControHandle  ;
}
else
{
sPush(h_ControHandle);
h_ControHandle=GetWindow(h_ControHandle,GW_HWNDNEXT);
if(!h_ControHandle)
{
while (!h_ControHandle && stack_Top>0)
{
        h_ControHandle=sPop();
h_ControHandle=GetWindow(h_ControHandle,GW_CHILD);
}
    if(stack_Top== 0)break;
}
  }
  }  // while(1) end
    break;
  }
  else
  {
h_WindowHandle=GetWindow(h_WindowHandle,GW_HWNDNEXT);
  }

  }

}

关注着。。。。

不怎么懂这方面的。。

Q:我想枚举一个进程(自己写的应用程序)中的所有句柄,包括线程,资源,文件等等。有什么好方法吗?
传说中的NtQuerySystemInformation可以吗。

A: NtQuerySystemInformation价格便宜量又足,我们一直用它

引用 17 楼 truelove7283159 的回复:
Q:我想枚举一个进程(自己写的应用程序)中的所有句柄,包括线程,资源,文件等等。有什么好方法吗?
传说中的NtQuerySystemInformation可以吗。

A: NtQuerySystemInformation价格便宜量又足,我们一直用它


听说过NtQuerySystemInformation,据说是Native API,CSDN中也有文章但不详尽.
偶试过没有成功,如果成功的话我贴上来.
有没有朋友有代码的让大家分享分享.

#include <windows.h>

#include <winternl.h>
//#pragma warning(disable:4786)
//#pragma warning(disable:4244)
#include <hash_map>
#include <hash_set>
#include <iostream>
using namespace std;
using namespace stdext;
hash_set <UINT32> g_HandleList;
hash_map <UINT32, UINT32> hadle_map;
typedef pair <UINT32, UINT32> hadle_Pair;

typedef UNICODE_STRING OBJECT_NAME_INFORMATION;
typedef UNICODE_STRING *POBJECT_NAME_INFORMATION;

#define ObjectNameInformation  1
#define SystemHandleInformation 0×10  //  Information  Class  16 
#define STATUS_SUCCESS                ((NTSTATUS)0×00000000L)
#define STATUS_INFO_LENGTH_MISMATCH  ((NTSTATUS)0xC0000004L)
#define STATUS_BUFFER_OVERFLOW        ((NTSTATUS)0×80000005L)

typedef struct _SYSTEM_HANDLE_ENTRY {
ULONG  OwnerPid;
BYTE  ObjectType;
BYTE  HandleFlags;
USHORT HandleValue;
PVOID  ObjectPointer;
ULONG  AccessMask;
} SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY;

typedef struct _SYSTEM_HANDLE_INFORMATION{
ULONG              Count;
SYSTEM_HANDLE_ENTRY Handle[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

#define CURRENT_PROCESS_HANDLE_MAX  102400
SYSTEM_HANDLE_ENTRY StructHandleList[CURRENT_PROCESS_HANDLE_MAX];  //all handle save

enum  { 
OB_TYPE_UNKNOWN  =  0, 
OB_TYPE_TYPE  =  1, 
OB_TYPE_DIRECTORY, 
OB_TYPE_SYMBOLIC_LINK, 
OB_TYPE_TOKEN, 
OB_TYPE_PROCESS, 
OB_TYPE_THREAD, 
OB_TYPE_UNKNOWN_7, 
OB_TYPE_EVENT, 
OB_TYPE_EVENT_PAIR, 
OB_TYPE_MUTANT, 
OB_TYPE_UNKNOWN_11, 
OB_TYPE_SEMAPHORE, 
OB_TYPE_TIMER, 
OB_TYPE_PROFILE, 
OB_TYPE_WINDOW_STATION, 
OB_TYPE_DESKTOP, 
OB_TYPE_SECTION, 
OB_TYPE_KEY, 
OB_TYPE_PORT, 
OB_TYPE_WAITABLE_PORT, 
OB_TYPE_UNKNOWN_21, 
OB_TYPE_UNKNOWN_22, 
OB_TYPE_UNKNOWN_23, 
OB_TYPE_UNKNOWN_24, 
OB_TYPE_CONTROLLER, 
OB_TYPE_DEVICE, 
OB_TYPE_DRIVER, 
OB_TYPE_IO_COMPLETION, 
OB_TYPE_FILE                                                 
}  SystemHandleType; 
//NtQuerySystemInformation
typedef DWORD (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG); 
//NtQueryObject
typedef DWORD (WINAPI *tNTQO)(HANDLE ObjectHandle, DWORD  ObjectInformationClass, PVOID ObjectInformation, DWORD Length, PDWORD  ResultLength);
//NtDeviceIoControlFile
typedef DWORD (WINAPI *tNTDIOCF)(HANDLE FileHandle, HANDLE Event,  PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,  DWORD IoControlCode, PVOID InputBuffer, DWORD InputBufferLength, PVOID  OutputBuffer, DWORD OutputBufferLength);

void EnableDebugPrivilege()
{
HANDLE hToken;
TOKEN_PRIVILEGES tokenPriv;
LUID luidDebug;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)!= FALSE)
{
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug) != FALSE)
{
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luidDebug;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL,NULL);
}
}
}
LPWSTR GetObjectName(HANDLE hObject)
{
LPWSTR lpwsReturn = NULL;
tNTQO pNTQO = (tNTQO)GetProcAddress(GetModuleHandle("NTDLL.DLL"),"NtQueryObject");
if (pNTQO != NULL)
{
DWORD dwSize = 200* sizeof(OBJECT_NAME_INFORMATION);
POBJECT_NAME_INFORMATION pObjectInfo = (POBJECT_NAME_INFORMATION)new BYTE[dwSize];
NTSTATUS ntReturn = pNTQO(hObject, ObjectNameInformation, pObjectInfo, dwSize, &dwSize);
if (ntReturn == STATUS_BUFFER_OVERFLOW)
{
delete pObjectInfo;
pObjectInfo = (POBJECT_NAME_INFORMATION)new BYTE[dwSize];
ntReturn = pNTQO(hObject, ObjectNameInformation, pObjectInfo, dwSize,&dwSize);
}
if ((ntReturn >= STATUS_SUCCESS) && (pObjectInfo->Buffer != NULL))
{
lpwsReturn = (LPWSTR)new BYTE[pObjectInfo->Length + sizeof(WCHAR)];
ZeroMemory(lpwsReturn, pObjectInfo->Length + sizeof(WCHAR));
CopyMemory(lpwsReturn, pObjectInfo->Buffer, pObjectInfo->Length);
}
delete pObjectInfo;
}
return lpwsReturn;
}

DWORD GetProcHandle(PSYSTEM_HANDLE_INFORMATION StructHandle,DWORD pid)
{

//1 init
DWORD re = STATUS_INFO_LENGTH_MISMATCH;
DWORD Count =0;
DWORD i, nedCount = 0, j = 0;
HINSTANCE NtdllDll = NULL;
  //  pid= GetCurrentProcessId();

//2 get system path and ntdll.dll
char mSystemPath[MAX_PATH+1];
memset(mSystemPath,0×00,MAX_PATH+1);
GetSystemDirectory(mSystemPath,MAX_PATH);
strcat(mSystemPath,"\\ntdll.dll");
NtdllDll = GetModuleHandle(mSystemPath);//LoadLibrary("ntdll.dll");
if(NtdllDll == NULL) 

return  0; 

//3 get func NtQuerySystemInformation
PROCNTQSI NtQuerySystemInformation  =  (PROCNTQSI)GetProcAddress(NtdllDll,"NtQuerySystemInformation");   
if (NtQuerySystemInformation == NULL)
{
return 0;
}

//4 get system handle list
DWORD dwSize = sizeof(SYSTEM_HANDLE_INFORMATION);
PSYSTEM_HANDLE_INFORMATION pHandleInfo = (PSYSTEM_HANDLE_INFORMATION) new BYTE[dwSize];
NTSTATUS ntReturn = NtQuerySystemInformation(SystemHandleInformation, pHandleInfo, dwSize, &dwSize);
   
//4.1 get all system handle count
if (ntReturn == STATUS_INFO_LENGTH_MISMATCH)
{
delete pHandleInfo;
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)new BYTE[dwSize];
ntReturn = NtQuerySystemInformation(SystemHandleInformation, pHandleInfo, dwSize, &dwSize);
}
   
//4.2 Enumerate all system handles
EnableDebugPrivilege();
//PrintProcessNameAndID(pid);
if (ntReturn == STATUS_SUCCESS)
{
for (DWORD dwIdx = 0; dwIdx <pHandleInfo->Count; dwIdx++)
{
//if (pHandleInfo->Handle[dwIdx].OwnerPid == pid)
{
HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE &brvbar PROCESS_QUERY_INFORMATION &brvbar PROCESS_VM_READ, FALSE, pHandleInfo->Handle[dwIdx].OwnerPid);
if (hProcess != INVALID_HANDLE_VALUE)
{
HANDLE hObject = NULL;
if (DuplicateHandle(hProcess, (HANDLE)pHandleInfo->Handle[dwIdx].HandleValue, GetCurrentProcess(), &hObject,STANDARD_RIGHTS_REQUIRED, FALSE, 0) != FALSE)
{
LPWSTR lpwsName = GetObjectName(hObject);
if (lpwsName != NULL)
{
wprintf(L"\nobject Name:\t%s ,object type:\t%d",lpwsName, pHandleInfo->Handle[dwIdx].ObjectType);
delete lpwsName;
}
CloseHandle(hObject);
}
LPWSTR lpwsName = GetObjectName((HANDLE)pHandleInfo->Handle[dwIdx].HandleValue);
if (lpwsName != NULL)
{
wprintf(L"\nobject Name:\t%s ,object type:\t%d",lpwsName, pHandleInfo->Handle[dwIdx].ObjectType);
delete lpwsName;
}

CloseHandle(hProcess);
}
nedCount++;
}
}
delete pHandleInfo;
}
return nedCount;
}

vc的代码,要改到bc的.
需要一些功力的.呵呵:)
我在vc下通过的,bc恩, 你就自己加油哈.

DWORD pID;
PROCESSENTRY32 lppe;
HANDLE  hSnapshot;
hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
lppe.dwSize = sizeof(lppe);
rValue=Process32First(hSnapshot,&lppe);
while(rValue)
{
if (ExtractFileName(lppe.szExeFile).LowerCase()=="watch.exe")//此处最好用字符串判等
  {
      pID=lppe.th32ProcessID;  //在此便得到了进程的ID
      break;
  }
  rValue=Process32Next(hSnapshot,&lppe); 
}
HANDLE pHandle=OpenProcess(PROCESS_ALL_ACCESS,false,pID);
if(!pHandle)
  ShellExecute(NULL,NULL,"d:\\watch\\watch.exe",NULL,"d:\\watch",SW_SHOW);
CloseHandle(hSnapshot);
*/

bool rValue;
DWORD pID;
PROCESSENTRY32 lppe;
HANDLE  hSnapshot;
hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
lppe.dwSize = sizeof(lppe);
rValue=Process32First(hSnapshot,&lppe);
for(pID=0; rValue; )
{
  if (ExtractFileName(lppe.szExeFile).LowerCase()=="watch.exe")
  {
      pID=lppe.th32ProcessID;  //在此便得到了进程的ID
      break;
  }
  rValue=Process32Next(hSnapshot,&lppe);
}
CloseHandle(hSnapshot);
if (pID==0)
  {
    rec->Add("Run Watch.exe at Time:"+Now().DateTimeString());
    rec->SaveToFile("record.txt");
    ShellExecute(NULL,NULL,"d:\\watch\\watch.exe",NULL,"d:\\watch",SW_SHOW);
    }

DWORD pID;
PROCESSENTRY32 lppe;
HANDLE  hSnapshot;
hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
lppe.dwSize = sizeof(lppe);
rValue=Process32First(hSnapshot,&lppe);
while(rValue)
{
if (ExtractFileName(lppe.szExeFile).LowerCase()=="watch.exe")//此处最好用字符串判等
  {
      pID=lppe.th32ProcessID;  //在此便得到了进程的ID
      break;
  }
  rValue=Process32Next(hSnapshot,&lppe); 
}
HANDLE pHandle=OpenProcess(PROCESS_ALL_ACCESS,false,pID);
if(!pHandle)
  ShellExecute(NULL,NULL,"d:\\watch\\watch.exe",NULL,"d:\\watch",SW_SHOW);
CloseHandle(hSnapshot);
*/

bool rValue;
DWORD pID;
PROCESSENTRY32 lppe;
HANDLE  hSnapshot;
hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
lppe.dwSize = sizeof(lppe);
rValue=Process32First(hSnapshot,&lppe);
for(pID=0; rValue; )
{
  if (ExtractFileName(lppe.szExeFile).LowerCase()=="watch.exe")
  {
      pID=lppe.th32ProcessID;  //在此便得到了进程的ID
      break;
  }
  rValue=Process32Next(hSnapshot,&lppe);
}
CloseHandle(hSnapshot);
if (pID==0)
  {
    rec->Add("Run Watch.exe at Time:"+Now().DateTimeString());
    rec->SaveToFile("record.txt");
    ShellExecute(NULL,NULL,"d:\\watch\\watch.exe",NULL,"d:\\watch",SW_SHOW);
    }

去试试看看。。呵呵。。
可能以后会用到~~

引用 15 楼 nihongsheng 的回复:
谢谢指点.但我认为进程下面的子句柄是线程,线程下面才是控件,从13楼我贴出的图片上可以看出.
画有二个齿轮的是进程,一个齿轮的是线程,再下面是各控件.可能你的办法也只能找到线程了.
我原也想这么干,我认为对话框是控件的容器,所以能用GetWindow(hParant,GW_CHILD)方法找,线程与控件可能不存在这个关系,所以能否用这个函数找我不敢确定.

进程就像一个目录,而线程则是这个目录下子目录,要遍历一个进程下所有句柄,就像遍历一个目录所以文件一样。
因此,可以用递归得到进程下所有句柄,不过只有进程和线程的话,再套一层while就行了。

控件的话,我觉得可以试着用FindWindowEx来查找句柄

请大家别把这个问题看得太简单了,我认为无论是进程快照还是GetWindow都较难实现,因为我已各种方法试验过多次了.我认为19楼的办法是正解.Native API是微软不公开的底层API,功能非常强大.,不仅仅能查看系统进程,包括其他进程线程信息,内存页表信息,io读写信息,CPU缓存信息,Native api 都位于NTDLL.DLL中,是用户层最底层的逻辑实现方式.
遗憾的是到现在还没有调试出来,还得努力学习提高.