Enumerate most top windows, list properties and get process

Share your advanced PureBasic knowledge/code with the community.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Enumerate most top windows, list properties and get process

Post 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
User avatar
idle
Always Here
Always Here
Posts: 5097
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

I'm sure that will come in handy, cheers
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

This is for PB 4.3?

Thank You for the code, it will come in handy. :)
akj
Enthusiast
Enthusiast
Posts: 665
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post 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
Anthony Jordan
Post Reply