获取线程的可见窗口标题 [英] Getting a thread's visible window's title

查看:114
本文介绍了获取线程的可见窗口标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何去做,因为我尝试了无数种不同的user32函数并在网上进行了广泛的研究,但不幸的是,我还无法提出解决方案.

I was wondering how I would go about doing this, as I've tried a myriad of different user32 functions and researched online quite extensively, but unfortunately I haven't been able to come up with a solution yet.

有一个具有5个线程的应用程序.可以通过.NET Process类GetProcessById方法轻松访问这些线程,前提是该进程具有PID.但是,似乎没有可以用来提供线程ID并枚举其窗口(父窗口或子窗口)的函数.这些线程之一共有10个窗口,其中9个隐藏且1个可见.该可见线程的标题是我想通过编程获得的.

There is an application that has 5 threads. These threads can easily be accessed via the .NET Process class GetProcessById method, provided the process' PID. However, it does not appear that there is a function that I can use to provide the Thread ID and enumerate its windows (parent or child). One of these threads has a total of 10 windows, 9 hidden and one visible. The title of that visible thread is what I am trying to get at programmatically.

我最新的方法是抓住进程句柄,将其放入EnumChildWindows,然后尝试以这种方式将每个窗口句柄添加到集合中,但是我的集合始终为空.

My latest approach has been to grab the process handle, put that through EnumChildWindows, and try to add each of the window handles to a collection that way, but my collection is always empty.

以下是我在ProcessThreadsView工具中看到的屏幕截图:

Here's a screenshot of what I see in the ProcessThreadsView tool:

有什么我想念的吗?我通过电子邮件向该工具的作者发送电子邮件,以了解他的工作方式,但是我想让大家看看是否有行之有效的方法.

Is there something I am missing? I emailed the author of the tool to see how he's doing it, but I figured I'd ask you guys to see if there is an established approach.

更新:我尝试使用GetGUIThreadInfo,这就是我的称呼方式:

Update: I have tried using GetGUIThreadInfo, this is how I am calling it:

[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,这就是我得到的:

Using EnumThreadWindows, this is what I've got:

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);
    }
}

推荐答案

(如果我之前的回答很苛刻,我深表歉意;我说看似显而易见",因为它对我来说很明显,所以我认为对OP也是显而易见的)因此是错误的,但是他没有提供有关未尝试过的任何细节.)

(Apologies if my previous answer came off harsh; I said "seemingly obvious" because it seemed obvious to me, so I assumed it was also obvious to the OP and thus wrong, but he did not give any details as to what had/hadn't been tried.)

EnumThreadWindows绝对是您想要的功能,它应该可以工作.对于系统上运行的每个应用程序,我都可以仅使用EnumThreadWindowsIsWindowVisible从ProcessThreadsView复制信息. (此外,请记住,可见"与活动"不同).

EnumThreadWindows is definitely the function you want, and it should work. I was able to replicate the information from ProcessThreadsView using just EnumThreadWindows and IsWindowVisible for every application running on my system. (Also, keep in mind that "visible" is not the same as "active").

[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会得到什么?您的回调会触发吗?

What exactly are you getting when you try EnumThreadWindows? Does your callback ever fire?

这篇关于获取线程的可见窗口标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆