C++Builder 程序员博客
30 Jun
通常如果已知一个窗体的名称,可以用Findwindow找到窗体句柄,再用Getwindows遍历窗体上控件,找到控件句柄.
这只是理想状态,有时弹出模式对话框根本就没有标题,从SPY++上就可以看出有很多是这种情况.我从SPY++上也看到可以通过进程的句柄,或线程的句柄下找到这些控件,网上多是遍历进程 和线程的文章,我已找到了进程或线程的句柄,如何遍历这进程或线程下的控件找到我需要的控件的句柄,一直没有成功,急请各位大侠指点.顿足拜谢.
注:所找到的进程是别的程序创建的,我不知代码的.
<img src="c:\u1.jpg" alt="0" />
枚举线程的窗口
EnumThreadWindows
我已找到了所有的进程,没有必要再枚举进程得到进程的名字了.我需要的是进程下各控件的句柄
这个就不怎么懂了,帮顶下吧,
等待结果~~~
<img src="c:\u1.jpg" alt="0" />
file:///d:/sss.jpg
比较汗….
我已枚举出了线程的窗口,得到的是线程的句柄,再往下如何得到线程下所有控件的句柄列表就不行了.
有一篇文章是用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
的所有子窗口。请注意,完成此过程需要花费一些时间。
先把图片传到晚上,然后点编辑框上面的插入图片就可以了。
控件也是有窗口的,枚举窗口为什么不能枚举的控件的?
咳,不知道是不是我理解错了,EnumThreadWindows列举的是窗口句柄而不是线程句柄!
下面是用EnumThreadWindows列举出本线程所有窗口的例子(所有窗口的标题放在Form1的Memo1里),如果楼主还要找这些窗口里的子控件,可以再用FindWindowEx或EnumChildWindows之类的方法找。
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)); } //—————————————————————————
这里控件是放在一个模式对话框里,标题栏是空的字符串,表面上看到的标题栏是一个Edit控件.而系统中存在大量"#32770"的对话框,它们的标题也各种各样,很可能就有空字符串,而它返回的是找到的第一个窗口的句柄,不能保证一定是你需要的.所以较为可行的方法是枚举系统当前的所有进程,从中查找模块名为您需要的进程,从进程中查找属于控件的句柄.
现在网上枚举窗口的方法绝大多数都是从一个对话框里找它上面控件的句柄,我因为这个对话框的句柄找不到,才想用进程或线程里找.
你把SPY++打开,调到查看线程或进程里,可以看到线程下面控件名及句柄.我想知道它是怎么出来的.
请告诉我传图片的方法,我上传一张图片给您瞧瞧
引用 10 楼 loveshell 的回复:]
先把图片传到晚上,然后点编辑框上面的插入图片就可以了。
控件也是有窗口的,枚举窗口为什么不能枚举的控件的?
[/Quote]
凭印象写的,没调试过。。。
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; }
谢谢指点.但我认为进程下面的子句柄是线程,线程下面才是控件,从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价格便宜量又足,我们一直用它
#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 ¦ PROCESS_QUERY_INFORMATION ¦ 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);
}
去试试看看。。呵呵。。
可能以后会用到~~
进程就像一个目录,而线程则是这个目录下子目录,要遍历一个进程下所有句柄,就像遍历一个目录所以文件一样。
因此,可以用递归得到进程下所有句柄,不过只有进程和线程的话,再套一层while就行了。
控件的话,我觉得可以试着用FindWindowEx来查找句柄
请大家别把这个问题看得太简单了,我认为无论是进程快照还是GetWindow都较难实现,因为我已各种方法试验过多次了.我认为19楼的办法是正解.Native API是微软不公开的底层API,功能非常强大.,不仅仅能查看系统进程,包括其他进程线程信息,内存页表信息,io读写信息,CPU缓存信息,Native api 都位于NTDLL.DLL中,是用户层最底层的逻辑实现方式.
遗憾的是到现在还没有调试出来,还得努力学习提高.