This request is somewhat weird. However, you can do it in the following way: get the HWND of the active (desktop-wide) main application window. Then list all the processes and retrieve the main window's HWND for those processes which have one. Traverse the set of such processes to compare this HWND with the HWND you found. When you find one, for the found process, locate the entry-point executable module of this process.
Let's start. To get this top-level window for a given main window, use the function
GetLastActivePopup
:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633507%28v=vs.85%29.aspx[
^].
In most cases, it will return the same main window handle, but we need to take into account the cases when some modal dialog is shown.
You may have a problem with the application which is executing some modal dialog on top of its main window. Then this dialog's HWND will be returned. Also, you need to know the owner window. Take the desktop HWND and list its children:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633504%28v=vs.85%29.aspx[
^],
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633494%28v=vs.85%29.aspx[
^],
or
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515%28v=vs.85%29.aspx[
^].
You can simply use
GetWindows
(see the last link above) with
uCmd
equal to
GW_CHILD
, using desktop as a parent, to retrieve the top child of the desktop in Z-order.
(Note: you cannot use Windows API
GetActiveWindow
, because it only can find the window if it is attached to the current thread, but your code's thread would be different.)
To use all these raw API functions, you will nee to use P/Invoke:
http://en.wikipedia.org/wiki/Platform_Invocation_Services[
^],
http://msdn.microsoft.com/library/en-us/vcmxspec/html/vcmg_PlatformInvocationServices.asp[
^],
http://www.pinvoke.net/[
^].
This CodeProject article can also be useful:
http://www.codeproject.com/csharp/EssentialPInvoke.asp[
^].
Now, let's go to the processes side. This is how you can list all processes:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.getprocesses%28v=vs.110%29.aspx[
^].
When this is done, you can examine its main window handle:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowhandle%28v=vs.110%29.aspx[
^].
The method referenced above should be called under the try-catch block, because not all processes have this window. And this is the way this method works: it throws an exception when a window handle cannot be found.
In a loop, compare window handles with the handle of the found active window handle and thus locate the process in question. Now you can locate its main executable module and then find the module's file name:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainmodule%28v=vs.110%29.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.diagnostics.processmodule%28v=vs.110%29.aspx[
^].
If you want, you can locate other modules of the active application found (if there are more of them) and do the same with each:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.modules(v=vs.110).aspx[
^].
Now, you can face one difficulty: if your process has a windowed UI or just a console, it will grab activation on itself, so you will loose the information on what application was active before. Moreover, even if your application does not have any windows (not even a console window) and just writes the result in some file (just for example), the application which you use to start your process (say, any Windows Shell application, or anything else) would steel the active status. So, you need something else to defer the code you use to determine the active application. One way could be using a global hot key:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx[
^],
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646327%28v=vs.85%29.aspx[
^].
These two hot key functions can be used the same was as other Window API functions, via P/Invoke.
That's all. Wow, it's was a long description… :-)
It's possible that the algorithm I tried to depict could be improved and clarified, especially during actual development. I guess, you need to do your part of job.
—SA