0

I want to read out all windows of a process. Then I want to check for all windows which have a bounds area > 0. These are the windows I want to work with but they should be visible. Now I have two problems:

  1. When I check the windows of spotify.exe I get multiple windows with an area > 0, but I know there is only one correct window.

Here the code:

[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processId) {
    var handles = new List<IntPtr>();

    foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
        EnumThreadWindows(thread.Id,
            (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);

    return handles;
}

[StructLayout(LayoutKind.Sequential)]
public struct RECT {
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

// --main--

foreach (Process p in Process.GetProcesses()) {
    try {
        if (p.ProcessName == "Spotify") {
            foreach (var hwnd in EnumerateProcessWindowHandles(p.Id)) {
                RECT rect = new RECT();

                if (!GetWindowRect(hwnd, out rect)) {
                    Console.WriteLine("Fail");
                    continue;
                }

                Console.WriteLine(string.Format("{0}: {1} {2} {3} {4}", hwnd, rect.Left, rect.Top, rect.Right, rect.Bottom));
            }
        }
    }
    catch (Win32Exception) { }
    catch (InvalidOperationException) { }
}

Output:

658638: 114 8 154 48
5114512: 1659 0 1794 31
132734: 98 0 1794 900
395348: 0 0 0 0
132744: 0 0 136 39
721406: 26 26 1466 815
132758: 0 0 0 0
854982: 0 0 0 0
132760: 0 0 0 0
132710: 0 0 1 1
198288: 0 0 0 0
132754: 0 0 136 39
198286: 0 0 0 0

When I look at the values it seems that the 3rd one is the correct one. Why can other window handles have an area when they are not visible or minimized?

  1. When I try to read out the windows of Windows Movies & TV all windows are 0,0,0,0. But I clearly see the window is visible on my 2nd screen so it should have an area. I use the same code, but instead of if (p.ProcessName == "Spotify") I use if (p.MainModule.FileName.Contains("WindowsApps") && p.MainModule.FileName.Contains("Video.UI.exe"))

Output:

1117438: 0 0 0 0
3150042: 0 0 0 0

Any Ideas?

P.S.: I don't use p.MainWindowHandle because it's too inconsequent. Sometimes it's 0 sometimes not. Depends on User interaction, windows visibility, ... So it's too unreliable. For Windows Movies & TV it's always 0.

Kaskorian
  • 426
  • 3
  • 18
  • "Why can other window handles have an area when they are not visible or minimized?" An invisible window can have area. That's probably what you're seeing. – Raymond Chen Jan 05 '21 at 20:18
  • Okay, I tried to restore and show all the windows read out and they actually have an area but they are just empty windows or white immovable rectangles. So is there a way to identify the correct one? Also what is with Movies & TV? – Kaskorian Jan 05 '21 at 20:50
  • Identifying the "correct" one is all a matter of defining what the "correct" one is. One definition is to find the largest (in terms of area) window that is visible. Another is to find the window that satisfies taskbar requirements. (Movies & TV is a UWP app, and they use a different app model>) – Raymond Chen Jan 05 '21 at 21:24
  • I know Movies & TV is a UWP app. Is the approach different? How do I get the window handles for a UWP app? – Kaskorian Jan 05 '21 at 22:22
  • UWP apps don't use windows in the traditional sense. The system creates a fake HWND for them, but the fake window isn't part of the app itself. What is your goal? As in, what do you intend to do with the windows once you've found them? – Raymond Chen Jan 05 '21 at 22:42
  • I want to move these windows to a specified screen and bring them to the front when needed – Kaskorian Jan 05 '21 at 22:43
  • SHGetPropertyStoreForWindow + IPropertyStore::GetValue(PKEY_AppUserModel_ID) will let you get the appid associated with a window. https://stackoverflow.com/a/35712620/902497 – Raymond Chen Jan 05 '21 at 22:45
  • I already have to AUMID from a *GlobalSystemMediaTransportControlsSession* – Kaskorian Jan 05 '21 at 22:47
  • But how do I move the window using this id. – Kaskorian Jan 05 '21 at 22:48
  • You move the HWND. – Raymond Chen Jan 05 '21 at 23:08
  • Could you be a bit more specific? First, you tell me how to get the AUMID which I already have but then you tell me I don't need it and I move the window by the HWND. Also, there is still the problem that I don't know which window to move because they all have an area of 0 – Kaskorian Jan 05 '21 at 23:22
  • [How do you programmatically resize and move windows with the Windows API?](https://stackoverflow.com/questions/692742/how-do-you-programmatically-resize-and-move-windows-with-the-windows-api). You use the AUMID to identify the window, and then you use SetWindowPos to move it. – Raymond Chen Jan 06 '21 at 14:31

0 Answers0