none
Finding HWND of metro app using Win32 API RRS feed

  • Question

  • In Win32, APIs like EnumWindows, EnumChildWindows, EnumThreadWindows can be used to get HWNDs of applications which are running. However, I found that EnumWindows and EnumThreadWindows don't return the correct HWND corresponding to Metro applications like "Weather", "Sports", etc. These APIs return some HWNDs for these applications, but those windows don't have names which can be obtained using GetWindowText and also calls like SetForegroundWindow don't work on them.

    Oddly, Process Explorer built in 2010 is able to successfully find the correct windows from these applications and use "bring to front" to bring them to the front.

    I am testing with Windows 8 Release Preview, using a win32 console app written using Microsoft Visual C++ 2010 Express.

    I tried to debugging process explorer using assembly and found that it passed a particular HWND to SetForegroundWindow function. If I modify my code to hard code this HWND pointer and call SetForegroundWindow or GetWindowText on it then it works perfectly. Even GetWindowThreadProcessId returns correct process and thread IDs.

    So, my question is how to find these special windows from Metro application using Win32 APIs?

    I know these windows are of class "Windows.UI.Core.CoreWindow". So a call to FindWindow with that class name returns one window (correct one) of any one the metro apps. But I am interested in getting all windows of all metro apps which are visible & enabled & return proper value in response to GetWindowText.

    Since Process Explorer written in 2010 is able to obtain these, it's definitely possible. I am afraid I am unable to find the right API. Any help is really appreciated.

    • Moved by Rob Caplan [MSFT]Microsoft employee Monday, October 15, 2012 11:07 PM Desktop app question, not a Windows Store app development (From:Building Windows Store apps with C++ )
    Monday, July 23, 2012 9:53 AM

Answers

  • Well, it seems with the final build on Windows 8 RTM, this issue has been fixed. EnumWindows, etc. are able to return correct windows for Metro apps also.

    However, as mentioned, Process Explorer was able to find the windows even in older Windows 8 build. I had debugged Process Explorer in assembly to find out how it does it in the next couple of days since posting the question. But I had forgotten to reply back. So, here are the details for any one interested.

    You can find out the process ID of an app, using EnumProcesses. After that FindWindowEx needs to be used in a particular manner as shown below to find the window. 

    HWND GetProcessWindow( DWORD processId )

    { // Now need to run a loop to get the correct window for process. bool bFound = false; HWND prevWindow = 0; while ( ! bFound ) { HWND desktopWindow = GetDesktopWindow(); if ( ! desktopWindow ) break; HWND nextWindow = FindWindowEx( desktopWindow, prevWindow, NULL, NULL ); if ( ! nextWindow ) break; // Check whether window belongs to the correct process. DWORD procId = -1; GetWindowThreadProcessId( nextWindow, &procId ); if ( procId == processId ) { // Add additional checks. In my case, I had to bring the window to front so these checks were necessary. wchar_t windowText[ 1024 ]; if ( IsWindowVisible( nextWindow ) && ! IsIconic( nextWindow ) && GetWindowText( nextWindow, ( LPWSTR )windowText, sizeof( windowText ) / sizeof( wchar_t ) ) && ! GetParent( nextWindow ) ) return nextWindow; } prevWindow = nextWindow; } return 0; }

    It is not obvious from the documentation of FindWindowEx that is works in this way. But Mark Russinovich knew. So, thanks to him, this works!!


    Monday, October 15, 2012 12:47 PM

All replies

  • Are you sure Process Explorer uses HWND-based APIs to bring those windows to the front? Metro is Direct3D based, so except for the top level window, there aren't any HWNDs involved there. So you might want to take a different approach here.

    http://blog.voidnish.com

    Monday, July 23, 2012 3:24 PM
  • Hi Nishant, 

    Thanks for your reply. I debugged process explorer to find that it uses SetForegroundWindow to bring the window to front. If I use that HWND handle in my code, then I am also able to get metro app window name and bring it to front. Also if I have just one metro app like Weather running in system, FindWindowW( L"Windows.UI.Core.CoreWindow", NULL ); returns me the HWND to Weather window.

    Yes, Metro is written on Direct3D, but internally it seems to use HWNDs. The process explorer build that I am using is quite old (2010).

    Tuesday, July 24, 2012 3:47 AM
  • Well, it seems with the final build on Windows 8 RTM, this issue has been fixed. EnumWindows, etc. are able to return correct windows for Metro apps also.

    However, as mentioned, Process Explorer was able to find the windows even in older Windows 8 build. I had debugged Process Explorer in assembly to find out how it does it in the next couple of days since posting the question. But I had forgotten to reply back. So, here are the details for any one interested.

    You can find out the process ID of an app, using EnumProcesses. After that FindWindowEx needs to be used in a particular manner as shown below to find the window. 

    HWND GetProcessWindow( DWORD processId )

    { // Now need to run a loop to get the correct window for process. bool bFound = false; HWND prevWindow = 0; while ( ! bFound ) { HWND desktopWindow = GetDesktopWindow(); if ( ! desktopWindow ) break; HWND nextWindow = FindWindowEx( desktopWindow, prevWindow, NULL, NULL ); if ( ! nextWindow ) break; // Check whether window belongs to the correct process. DWORD procId = -1; GetWindowThreadProcessId( nextWindow, &procId ); if ( procId == processId ) { // Add additional checks. In my case, I had to bring the window to front so these checks were necessary. wchar_t windowText[ 1024 ]; if ( IsWindowVisible( nextWindow ) && ! IsIconic( nextWindow ) && GetWindowText( nextWindow, ( LPWSTR )windowText, sizeof( windowText ) / sizeof( wchar_t ) ) && ! GetParent( nextWindow ) ) return nextWindow; } prevWindow = nextWindow; } return 0; }

    It is not obvious from the documentation of FindWindowEx that is works in this way. But Mark Russinovich knew. So, thanks to him, this works!!


    Monday, October 15, 2012 12:47 PM
  • Hi Chandranath,

    I am looking for the same code in C# or Powershell. If possible, share the code so it may helpful for all of us.

    Wednesday, March 26, 2014 4:07 AM