.EXE name of topmost application

Share your advanced PureBasic knowledge/code with the community.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

.EXE name of topmost application

Post by blueznl »

Probably listed a zillion times elsewhere, but perhaps it will save someone searching... I should mess around a little to support other flavors of Windows as well... and account for Unicode versus non-Unicode but duh. It leaves something for you to do 8)

Code: Select all

#kernel32 = 1
;
buffer.s{512}
max.i = Len(buffer)-2
window_h.i
window_name.s
process_id.i
process_h.i
application_name.s
;
; GetModuleFIleNameEx is not by default included in PureBasic, so open the appropriate DLL or LIB
; (Psapi.lib on Windows XP?)
;
OpenLibrary(#kernel32,"kernel32.dll")
;
; GetModuleFileNameW is the unicode version of GetModuleFileName
; Windows 7 complicates matters a bit, but K32GetModuleFileNameExW seems to work fine on Win7
;
; classic way by locating and executing the function
;
;   K32GetModuleFileNameExW_ = GetFunction(#kernel32,"K32GetModuleFileNameExW")
;   l = CallFunctionFast(K32GetModuleFileNameExW_ ,process_h, 0, @buffer, max)
;   application_name = PeekS(@buffer,l)
;
; the alternative way using a prototype
;
;   Prototype K32GetModuleFileName_(process_h.i, module_h.i, buffer_p.i, buffer_l.i)
;   K32GetModuleFileName_.K32GetModuleFileName_ = GetFunction(#kernel32,"K32GetModuleFileNameExW")
;   l = K32GetModuleFileName_(process_h,0,@buffer,max)
;   application_name = PeekS(@buffer,l)
;
; prototypes make more sense when you repeatedly call the function in question
;
Prototype K32GetModuleFileName_(process_h.i, module_h.i, buffer_p.i, buffer_l.i)
K32GetModuleFileName_.K32GetModuleFileName_ = GetFunction(#kernel32,"K32GetModuleFileNameExW")
;
window_h = GetForegroundWindow_()
If window_h <> 0
  l = GetWindowText_(window_h,@buffer,max)
  window_name = PeekS(@buffer,l)
  GetWindowThreadProcessId_(window_h,@process_id)
  If process_id <> 0
    process_h = OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ , #False, process_id)
    If process_h <> 0
      l = K32GetModuleFileName_(process_h,0,@buffer,max)
      application_name = PeekS(@buffer,l)
    EndIf
  EndIf
  ;
  Debug window_name
  Debug application_name
EndIf
;
CloseLibrary(#kernel32)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Re: .EXE name of topmost application

Post by Nico »

GetModuleFileNameExW work fine here in window 7, are you an example where GetModuleFileNameExW fail?
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: .EXE name of topmost application

Post by luis »

MSDN wrote: The GetModuleFileNameEx function is primarily designed for use by debuggers and similar applications that must extract module information from another process. If the module list in the target process is corrupted or is not yet initialized, or if the module list changes during the function call as a result of DLLs being loaded or unloaded, GetModuleFileNameEx may fail or return incorrect information.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: .EXE name of topmost application

Post by blueznl »

IIRC GetModulueFilenameEx (the ...A and ...W versions both) are not implemented on all platforms. The K32... variant was listed as the prefered function name on Windows 7 and later.

As for the (inconsistency) of using K32GetModuleFilenameEx... MSDN isn't always clear, and some older approach (can't recall the name of that API anymore) was deprecated, so I ended up with K32...

Anyway, I was working on an old application UniRun, that allows startup of many different emulators, and wanted to detect every the user 'tabbed away' from an active emulator. In some cases, tabbing out would mess up the system, which could only be told to behave itself by killing the misbehaving application. As I wasn't always launching the application in question myself, and the windows name seemed to be somewhat random, all I could do is check the .exe name behind it.

Anyway, it works :-) like this: check topmost app every 5 secs by process ID, if it changed check out the .EXE name, if the .EXE name warrants special action then take it, and remember the name of the new topmost app to detect further changes.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Post Reply