Page 1 of 1

Enumerate most top windows, list properties and get process

Posted: Tue Dec 16, 2008 12:16 am
by Rescator
This came about due to some code I needed for a program,
this is the test code that I initially made to try things out.

Hopefully someone else might find this interesting as well.

Find out all the "secrets" the windows in your system have.

Some parts of the source is commented out so that by running it as it is
you will only get windows with a window title listed, and the topmost window (as close to the root as it can find), then get the process id and fetch info like exe or filename name as well.

Some source is commented out so that only window properties with a actual property name is listed, the atom ones are not.
Those are usually temporary and can not be relied upon, but many of those named properties tend to be used again and again.

To get a property just use GetProp_() and to set a property (like for example add one to your own programs window9 just use SetProp_()
remember to use use RemoveProp_() if you use SetProp_() though to avoid memory leaks when closing your window.

Anyway, run, have fun peeking at what window properties all your systems windows have.

PS! If running on a limited user account you will most likely not see admin or any other high elevation windows, in that case running the your prog as admin might should do the trick and show you other windows.
Unless this is only limited to current desktop or session only, I haven't checked.

You'll have to redo the code though as I simply was lazy and used Debug for testing text output :P

Code: Select all

EnableExplicit

Procedure.s ProcessNameFromHwnd(hwnd)
 Protected processid.l,psapilib.l,processname$,GetModuleFileNameEx,hprocess.l
 psapilib=OpenLibrary(#PB_Any,"psapi.dll")
 If psapilib
  CompilerIf #PB_Compiler_Unicode
   GetModuleFileNameEx=GetFunction(psapilib,"GetModuleFileNameExW")
  CompilerElse
   GetModuleFileNameEx=GetFunction(psapilib,"GetModuleFileNameExA")
  CompilerEndIf
  If GetModuleFileNameEx
   If GetWindowThreadProcessId_(hwnd,@processid)
    hprocess=OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ,#Null,processid)
    If hprocess
     processname$=Space(#MAX_PATH)
     If Not CallFunctionFast(GetModuleFileNameEx,hprocess,#Null,@processname$,#MAX_PATH)
      processname$=""
     EndIf
     CloseHandle_(hprocess)
    EndIf
   EndIf
  EndIf
  CloseLibrary(psapilib)
 EndIf
 ProcedureReturn processname$
EndProcedure

Procedure.l _PropEnumProc(hwnd.i,*string,hdata.i)
 Protected result.l=#True,text$
 If *string>$FFFF
  text$=PeekS(*string)
  Debug "Prop: "+#DQUOTE$+text$+#DQUOTE$+" = $"+Hex(hdata)
 ;Else ;ATOM prop, not a string, so not that interesting for us normally.
 ; text$="$"+Hex(*string)
 ; Debug "Prop: $"+Hex(*string)+" = $"+Hex(hdata)
 EndIf
 ProcedureReturn result
EndProcedure

Global NewList windowhandles.i()
Procedure.l _EnumWindowsProc(hwnd.i,param.i)
 Protected result.l=#True,titlelen.l,title$,processname$,hwnd2.i,found.l
 hwnd=GetAncestor_(hwnd,#GA_ROOTOWNER)
 found=#False
 If ListSize(windowhandles())>0
  ForEach windowhandles()
   If hwnd=windowhandles()
    found=#True
    Break
   EndIf
  Next
 EndIf
 If Not found
  LastElement(windowhandles())
  AddElement(windowhandles())
  windowhandles()=hwnd
 EndIf
 ProcedureReturn result
EndProcedure

EnumWindows_(@_EnumWindowsProc(),#Null)

Define hwnd.i,titlelen.l,title$,processname$
ForEach windowhandles()
 hwnd=windowhandles()
 titlelen=GetWindowTextLength_(hwnd)
 If titlelen
  title$=Space(titlelen)
  GetWindowText_(hwnd,title$,titlelen+SizeOf(Character))
  processname$=ProcessNameFromHwnd(hwnd)
  If processname$<>""
   Debug "Process: "+#DQUOTE$+processname$+#DQUOTE$
   Debug "Window: $"+Hex(hwnd)+" "+#DQUOTE$+title$+#DQUOTE$
   EnumProps_(hwnd,@_PropEnumProc())
   Debug ""
  EndIf
 ;Else ;No window title, most likely a special window, not intersting for us normally.
 ; title$=""
 ; processname$=ProcessNameFromHwnd(hwnd)
 ; Debug "Process: "+#DQUOTE$+processname$+#DQUOTE$
 ; Debug "Window: $"+Hex(hwnd)+" "+#DQUOTE$+title$+#DQUOTE$
 ; EnumProps_(hwnd,@_PropEnumProc())
 ; Debug ""
 EndIf
Next

Posted: Tue Dec 16, 2008 4:59 am
by idle
I'm sure that will come in handy, cheers

Posted: Tue Dec 16, 2008 11:16 am
by SFSxOI
This is for PB 4.3?

Thank You for the code, it will come in handy. :)

Posted: Tue Dec 16, 2008 3:04 pm
by akj
@Rescator:

Your routine ProcessNameFromHwnd() does not work under my Windows ME so I've added some extra code and it now does

Code: Select all

Procedure.s ProcessNameFromHwnd(hwnd)
 Protected processid.l,psapilib.l,processname$,GetModuleFileNameEx,hprocess.l
 Protected hsnp, mod.MODULEENTRY32, found ; AKJ
 psapilib=OpenLibrary(#PB_Any,"psapi.dll")
 If psapilib
  CompilerIf #PB_Compiler_Unicode
   GetModuleFileNameEx=GetFunction(psapilib,"GetModuleFileNameExW")
  CompilerElse
   GetModuleFileNameEx=GetFunction(psapilib,"GetModuleFileNameExA")
  CompilerEndIf
  If GetModuleFileNameEx
   If GetWindowThreadProcessId_(hwnd,@processid)
    hprocess=OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ,#Null,processid)
    If hprocess
     processname$=Space(#MAX_PATH)
     If Not CallFunctionFast(GetModuleFileNameEx,hprocess,#Null,@processname$,#MAX_PATH)
      processname$=""
     EndIf
     CloseHandle_(hprocess)
    EndIf
   EndIf
  EndIf
  CloseLibrary(psapilib)
 Else ; If psapi library failed to open
  ; Get process ID and snapshot
  GetWindowThreadProcessId_(hwnd, @processid)
  hsnp = CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, processid)
  If hsnp<>#INVALID_HANDLE_VALUE ; -1
   ; Use the snapshot to determine the process name
   mod\dwSize = SizeOf(MODULEENTRY32)
   found = Module32First_(hsnp, mod)
   While found
    processname$ = PeekS(@mod\szExePath)
    If UCase(Right(processname$, 4))=".EXE": Break: EndIf
    processname$ = ""
    found = Module32Next_(hsnp, mod)
   Wend
   CloseHandle_(hsnp)
  EndIf
 EndIf
 ProcedureReturn processname$
EndProcedure