全部打开 windows

Get ALL open windows

我正在开发一个 WPF 应用程序,我需要一种方法来获取应用程序中所有打开的 windows,包括从另一个线程打开的那些。我试过 Application.Current.Windows 但这并没有给我从另一个线程打开的 windows。甚至可以访问另一个线程打开的 windows 吗?不应该所有 windows 都在同一个应用程序域中吗?

谢谢。

Window class 检查当前应用程序的调度程序是否是当前线程的调度程序,如果是则将其添加到 Windows 集合中。这些其他 windows 看起来不像是在 public 集合中公开的,但是 Application 上有一个内部 属性,NonAppWindowsInternal 具有 windows.

我总是会在单个 UI 线程上创建 UI 个对象。如果这样做,您将可以通过 Application.Current.Windows.

访问所有 Window 对象

这应该可以做到。它将 return 一个整数指针列表,指向给定应用程序名称的每个打开 window:

public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

static void Main(string[] args)
{
    Process[] processes = Process.GetProcessesByName("MyApp");

    var windows = new List<IntPtr>();

    foreach (Process p in processes)
    {
        IEnumerable<IntPtr> w = GetRootWindowsOfProcess(p.Id);
        windows.AddRange(w);
    }
}

private static IEnumerable<IntPtr> GetRootWindowsOfProcess(int pid)
{
    IEnumerable<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
    var dsProcRootWindows = new List<IntPtr>();
    foreach (IntPtr hWnd in rootWindows)
    {
        uint lpdwProcessId;
        GetWindowThreadProcessId(hWnd, out lpdwProcessId);
        if (lpdwProcessId == pid)
            dsProcRootWindows.Add(hWnd);
    }
    return dsProcRootWindows;
}

private static IEnumerable<IntPtr> GetChildWindows(IntPtr parent)
{
    var result = new List<IntPtr>();
    GCHandle listHandle = GCHandle.Alloc(result);
    try
    {
        var childProc = new Win32Callback(EnumWindow);
        EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
    }
    finally
    {
        if (listHandle.IsAllocated)
            listHandle.Free();
    }
    return result;
}

private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
    GCHandle gch = GCHandle.FromIntPtr(pointer);
    var list = gch.Target as List<IntPtr>;
    if (list == null)
    {
        throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
    }
    list.Add(handle);
    //  You can modify this to check to see if you want to cancel the operation, then return a null here
    return true;
}

正如其中一位评论者所提到的,您不应该让多个线程执行 GUI 工作。一个线程应该执行 GUI 绘图,而其他线程执行实际的其他工作。

我不确定这个解决方案,但这是我发现最接近的解决方案。

尝试获取进程:

using System.Diagnostics;

Process[] processlist = Process.GetProcesses();

foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        Console.WriteLine("Process: {0} ID: {1} Window title: {2}", process.ProcessName, process.Id, process.MainWindowTitle);
    }
}

如果这没有帮助,请尝试使用 Process.GetProcessesByName("ApplicationName") 并查看结果 returns。

查看 this solution and the MSDN class page 和其中可用的方法也可能有所帮助。