MSDN Magazine > Issues and Downloads > 2002 > July >  C++ Q&A: Get the Main Window, Get EXE Name
From the July 2002 issue of MSDN Magazine
Get the Main Window, Get EXE Name
Download the code for this article: CQA0207.exe (72KB)
Q How can I find the main window for a process? I'm writing a Spy-like tool and I need to get the main window (HWND) for a process so I can send it a message like WM_ACTIVATEAPP.
John Riggins

A Which main window do you mean? A process can have more than one. Microsoft® Outlook® is a good example. If you start Outlook, you get a window listing your Inbox and other folders. If you open e-mail, you get another window that displays the message. Both are main windows in the sense that they have no parent or owner. If you whip out your trusty Spy tool, you can see they even have the same class name: rctrl_renwnd32. In general there's no way to tell (say, from the style flags or class name) which window is the "real" main window.
      That said, finding the (possibly multiple) main windows is easy. You can use EnumWindows and GetWindowThreadProcessId to find all top-level windows with a process ID that matches the one you're looking for. I wrote a little class, CMainWindowIterator, that does what you want (see Figure 1).
DWORD pid = // some process id
CMainWindowIterator itw(pid);
for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next()) {
  // do something
}
      What could be easier? CMainWindowIterator derives from a more generic class, CWindowIterator, that wraps ::EnumWindows in C++ to hide the clunky callback. CWindowIterator has a virtual OnWindow function you can override in derived classes to enumerate windows that meet whatever criteria you like. CMainWindowIterator overrides OnWindow to include only windows that belong to the given process.
// (m_pid is set in ctor)
BOOL CMainWindowIterator::OnWindow(HWND hwnd)
{
  if ((GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE)) {
    DWORD pidwin;
    GetWindowThreadProcessId(hwnd, &pidwin);
    if (pidwin==m_pid)
      return TRUE;
  }
  return FALSE;
}
      In other words, a window is a main window of a process if it has no parent (implied since CWindowIterator uses ::EnumWindows), is visible, and has the desired process ID. It's important to check WS_VISIBLE since some apps create lots of invisible top-level windows. (For an example of a program that uses CMainWindowIterator, read on.)
      If you're using .NET, you can get the main window handle of a Process object from the property Process.MainWindowHandle. For example, in C#:
Process p = // get process object;
IntPtr hwnd = p.MainWindowHandle;
Apparently, somewhere deep inside itself, Windows® does in fact know which window is "the" main window. Alas, I was unable to discover any way of obtaining this window through C/C++.

Q How can I find the name of the program file (EXE) associated with another process? I've tried various combinations of GetModuleFileName, GetModuleInstance, and GetModuleHandle, but nothing seems to work.
Frank Weston

A The problem with these calls is that they work only for modules loaded within the current running process, not modules in a different process. For that, you need something else, and here the road forks. If you're writing for Windows NT® 4.0, Windows 2000, or Windows XP, you can use PSAPI, a relatively new DLL with functions to get information about processes and modules. If you're writing for Windows 95, Windows 98, or Windows Me, you'll have to use ToolHelp. Since I'm so modern, I'll show you how to do it the PSAPI way. For help with ToolHelp, see Article Q175030, "HOWTO: Enumerate Applications in Win32" on MSDN®.
      One of the functions in PSAPI is GetModuleFileNameEx. It takes a process and module handle and gets the name of the module. How do you know which module in a process is the EXE that started it? There's another PSAPI function, EnumProcessModules, that stuffs an array with module handles for all the modules in a process. The first entry is always the main module, so you can write
DWORD count;
HMODULE hm[1];
EnumProcessModules(hProcess, hm, 1, &count);
to get the first HMODULE, then call GetModuleFileNameEx. To show how it works in practice, I wrote a little program, lp, that lists processes with their module names and main windows (see Figure 2). Figure 3 shows a sample run. (Note that Windows Explorer and Outlook both have two "main" windows.)

Figure 3 Sample Run
Figure 3 Sample Run

The lp program uses a third PSAPI function, EnumProcesses, to enumerate all the running processes, but following the same idea as CWindowIterator and CMainWindowIterator from the previous question, I encapsulated the gory aspects of EnumProcesses and EnumProcessModules in two iterator classes, CProcessIterator and CProcessModuleIterator (see Figure 4 and Figure 1). With these classes in hand, lp is pretty straightforward. To iterate the processes, try the following:
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
  // handle each process
}
And here's how to get the name of the EXE that created the process:
CProcessModuleIterator itm(pid);
HMODULE hModule = itm.First(); // .EXE
TCHAR modname[_MAX_PATH];
GetModuleBaseName(itm.GetProcessHandle(),
 hModule, modname, _MAX_PATH);
      Since lp displays just the base module file name, not the full path name, I use another PSAPI function, GetModuleBaseName, instead of GetModuleFileNameEx. And since CProcessModuleIterator opens the process to enumerate the modules, I don't have to call OpenProcess. Instead, I can use CProcessModuleIterator::GetProcessHandle to get the already open process handle. Then lp uses CMainWindowIterator with each process to display the HWNDs of all the main windows. The bulk of lp is the logic to interpret command-line switches. For example, -c lists the window class names, and -t the titles.
      Since that was so easy, I wrote lp again just for fun, this time in C# (see Figure 5). Not surprisingly, things are a lot easier with .NET. There's no need for PSAPI or home-grown iterator classes; .NET already has all the classes you need to navigate processes and modules. Process.GetProcesses returns an array of Process objects, all the processes in the system. From each Process object you can get its main module and window handle.
Process[] procs = Process.GetProcesses();
int len = procs.GetLength(0);
for (int i=0; i<len; i++) {
  Process p = procs[i];
  if (p.Id!=0) {
    int hwnd = p.MainWindowHandle.ToInt32();
    if (hwnd!=0) { // if has a main window:
      ProcessModule pm = p.MainModule;
      String modname = pm.ModuleName;
      •••
    }
  }
}
      p.MainModule is the main (EXE) module (to get all of them, use p.Modules, a ProcessModuleCollection) and p.MainWindowHandle is the main window handle. (See my comments at the end of the preceding question about this strange but useful property.) While lp is a lot simpler in C#, all that ease-of-programming comes at a cost. When I run the C++ version of lp, the response is instantaneous. From the moment I press Enter to the moment the output appears, there's no delay I can humanly perceive. With .NET, it takes a long second—even with 768MB. C# and .NET just can't deliver the speed of C/C++ and native APIs. This should come as no surprise, knowing all that goes on behind the magic curtain. Of course, no programmer in his right mind would use .NET to write a console app, except as a learning exercise. That would be like firing up the space shuttle to get groceries. Did you ever notice the "net" in .NET? That means .NET is aimed at Web apps, where a few bazillion extra CPU cycles is nothing among friends, and gigabyte servers can be preloaded up the wazoo.

Update

      In my May column, Destin Szelong asked a question about function hiding. This happens when you have a base class with overloaded virtual functions and you override one in a derived class. The other functions are not automatically inherited, because once the compiler finds the function name in the derived scope, it looks no further. In May, I showed how to get around the function hiding problem by defining a derived class function that explicitly calls the base class.
class D : public B {
public:
    virtual void test(int x) {
        B::test(x); // call base explicitly
    }
};
      As several readers including guru Scott Meyers pointed out, there's another way.
class D : public B {
public:
    using B::test;
    // other test overrides
};
This brings B::test into the scope of D. It has the advantage that you don't have to rewrite D if someone expands B with more overloaded test functions. Not to mention it requires less typing! When you use using, all overloaded B::test functions come into D's scope and are thus inherited. This may be an advantage or disadvantage, depending on what you're trying to do. If you want to keep some test functions hidden from consumers of D, you can use my first method (call base explicitly), or make the functions you want to hide private or protected. If you read Scott's book More Effective C++ (Addison-Wesley, 1995), you'll learn on pages 143-144 that you can even use using to circumvent the privacy of base classes.
class B { // some class
public:
    func1();
    func2(double d);
    virtual test();
    virtual test(int x);
};

// D is privately derived from B
class D : private B {
public:
    // make all B::test fns public!
    using B::test;
};
This trick is expedient when B should properly be hidden, but has one or two functions you want to expose. All of which goes to prove that in C++, there's never only one way to skin a cat.
      Happy programming!

Send questions and comments for Paul to cppqa@microsoft.com.
Paul DiLascia is a freelance writer, consultant, and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++ (Addison-Wesley, 1992). Paul can be reached at askpd@pobox.com or http://www.dilascia.com.

Page view tracker