我想知道如何去做这件事,因为我已经尝试了许多不同的user32函数,并在网上进行了相当广泛的研究,但不幸的是我还没有能够提出解决scheme。
有一个应用程序有5个线程。 通过.NET Process类GetProcessById方法可以轻松地访问这些线程,并提供进程的PID。 但是,似乎没有一个函数可以用来提供线程ID并枚举它的窗口(父或子)。 其中一个线程总共有10个窗口,9个隐藏,一个可见。 该可见的线程的标题是我想要以编程方式获得。
我最新的方法是抓住进程句柄,通过EnumChildWindows,并尝试将每个窗口句柄添加到集合,但我的集合总是空的。
以下是我在ProcessthreadsView工具中看到的屏幕截图:
为什么EM_SETMARGINS在Windows 7下不起作用?
C ++ GUI教程:对textout的未定义引用
Java服务与GUI工具
用asynchronousftp操作连接GUI界面
在C,multithreading,多个窗口调用一个窗口过程,将每个调用使用新的局部variables,或者我需要一个互斥体?
有什么我失踪? 我发邮件给这个工具的作者,看看他是怎么做的,但我想我会问你们是否有一个确定的方法。
更新:我已经尝试使用GetGUIThreadInfo,这是我如何调用它:
[StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left; public int Top; public int Right; public int Bottom; } [StructLayout(LayoutKind.Sequential)] public struct GUITHREADINFO { public uint cbSize; public uint flags; public IntPtr hwndActive; public IntPtr hwndFocus; public IntPtr hwndCapture; public IntPtr hwndMenuOwner; public IntPtr hwndMoveSize; public IntPtr hwndCaret; public Rect rcCaret; } static IEnumerable<IntPtr> EnumerateThreadWindowHandlesByProcessId(int processId) { List<IntPtr> threadWindowHandles = new List<IntPtr>(); foreach (Processthread thread in Process.GetProcessById(processId).Threads) { GUITHREADINFO threadInfo = new GUITHREADINFO(); threadInfo.cbSize = (uint)Marshal.SizeOf(threadInfo); bool returnValue = GetGUIThreadInfo((uint)thread.Id,out threadInfo); threadWindowHandles.Add(threadInfo.hwndActive); } return threadWindowHandles; }
更新2:
使用EnumThreadWindows,这是我得到的:
public delegate bool EnumThreadDelegate(IntPtr hWnd,IntPtr lParam); [DllImport("user32.dll")] static extern bool EnumThreadWindows(int dwThreadId,EnumThreadDelegate lpfn,IntPtr lParam); private static bool ThreadWindows(IntPtr handle,IntPtr param) { //get window from handle later,testing for Now logger.Info("foo bar"); return true; } [STAThread] public void Execute() { Process[] processes = Process.GetProcessesByName("MyProcessName"); Process processOfInterest = processes[0]; foreach (Processthread thread in processOfInterest.Threads) { EnumThreadWindows(thread.Id,new EnumThreadDelegate(ThreadWindows),IntPtr.Zero); } }
通过Linuxterminal运行Java GUI应用程序
使用Tab移动到主应用程序窗口中的另一个编辑控件
基于Windows GUI的任务自动化
对话使用分析/热图工具
embedded式web浏览器
我相信你正在寻找GetGUIThreadInfo 。
更新 :你的p / invoke有几个错误。
rect字段是错误的(不是这里真的很重要)。 用这个:
[StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left; public int Top; public int Right; public int Bottom; }
而不是System.Drawing.Rectangle 。
其他字段的类型声明也是关闭的。 应该是这样的:
[StructLayout(LayoutKind.Sequential)] public struct GUITHREADINFO { public uint cbSize; public uint flags; public IntPtr hwndActive; public IntPtr hwndFocus; public IntPtr hwndCapture; public IntPtr hwndMenuOwner; public IntPtr hwndMoveSize; public IntPtr hwndCaret; public Rect rcCaret; }
您将明智地检查您的返回值,并在您的DllImport属性中使用SetLastError = true ,以便您可以辨别函数调用失败的原因。 此外,你应该通过ref传递结构,因为你传递的结构大小。
[DllImport("user32.dll",SetLastError=true)] static extern bool GetGUIThreadInfo(uint idThread,ref GUITHREADINFO lpgui);
使用Marshal.GetLastWin32Error()获取错误代码。 但是只有在GetGUIThreadInfo返回false的情况下才能检查。
通过上述更改,当给定一个有效的线程ID时,对GetGUIThreadInfo的调用将起作用。 另外请注意,其他进程需要有输入焦点,以使GetGUIThreadInfo返回任何有用的东西。
如果指定的线程不存在或没有输入队列,则该函数将失败。
(道歉,如果我以前的回答来得严厉;我说“看似明显”,因为它似乎很明显,所以我认为这也是显而易见的,因此是错误的,但他没有给出任何细节,没有被试过。)
EnumThreadWindows绝对是你想要的功能,它应该工作。 我能够使用EnumThreadWindows和IsWindowVisible从ProcessthreadsView中复制我系统上运行的每个应用程序的信息。 (另外请记住,“可见”与“有效”不一样)。
[UnmanagedFunctionPointer(CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.Bool)] private delegate bool EnumThreadWindowsProc(IntPtr handle,int param); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool EnumThreadWindows(uint threadId,EnumThreadWindowsProc callback,int param); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWindowVisible(IntPtr handle); [DllImport("user32.dll",CharSet = CharSet.Unicode)] static extern int GetwindowText( IntPtr handle,[MarshalAs(UnmanagedType.LPWStr)] StringBuilder caption,int count); [DllImport("user32.dll",CharSet = CharSet.Unicode)] static extern int GetwindowTextLength(IntPtr handle); static void Main(string[] args) { var callback = new EnumThreadWindowsProc(Program.ThreadWindows); foreach (var proc in Process.GetProcesses()) { foreach (Processthread thread in proc.Threads) { Program.EnumThreadWindows((uint)thread.Id,callback,0); } } Console.ReadLine(); } private static bool ThreadWindows(IntPtr handle,int param) { if (Program.IsWindowVisible(handle)) { var length = Program.GetwindowTextLength(handle); var caption = new StringBuilder(length + 1); Program.GetwindowText(handle,caption,caption.Capacity); Console.WriteLine("Got a visible window: {0}",caption); } return true; }
当你尝试使用EnumThreadWindows的时候你究竟得到了什么? 你的回调有没有触发?
你的代码更新2是好的(假设eraAccessprocess实际上是为了processOfInterest )。 该代码有效。 我能看到的唯一可能的失败原因是:
processOfInterest不是你真正感兴趣的过程。
该进程确实没有与Windows关联的线程。