[Solved] How to detect apps running in the system tray?

Windows specific forum
BarryG
Addict
Addict
Posts: 4168
Joined: Thu Apr 18, 2019 8:17 am

[Solved] How to detect apps running in the system tray?

Post by BarryG »

I need to know if an app is running when the only indication of it is its icon in the system tray (ie. no other open window on the desktop). Before you ask, I won't know its exe name so can't look for that as a running process. The end goal is to obtain a list of all open apps, and I can of course easily find all opened and minimized app windows, but not system-trayed ones. So, how would you go about this? Thanks.
Last edited by BarryG on Wed Mar 01, 2023 3:09 am, edited 1 time in total.
AZJIO
Addict
Addict
Posts: 2183
Joined: Sun May 14, 2017 1:48 am

Re: How to detect apps running in the system tray?

Post by AZJIO »

Find window Shell_TrayWnd, get ToolbarWindow32, count number of icons with TB_BUTTONCOUNT, get button text.
Look for the TB_BUTTONCOUNT constant in the "winapi_library" archive code, there are 3 examples there.

So that you do not suffer from searches, I took an example from there:

Code: Select all

; Author: NM, RASHAD

EnableExplicit

Define EventID
Define x
Global count,turn,hWnd,HDN,Name$
Global Dim Stray$(50),Dim Icon(50),Dim HDname$(12)

Structure TRAYDATA
  hwnd.i
  uID.l
  uCallbackMessage.l
  Reserved.l[2]
  hIcon.i
EndStructure

Structure TRAYDATA_wow64
  hwnd.q
  uID.l
  uCallbackMessage.l
  Reserved.l[2]
  hIcon.i
EndStructure

Structure TBBUTTON_wow64
  iBitmap.l
  idCommand.l
  fsState.b
  fsStyle.b
  bReserved.b[6]
  dwData.q
  iString.q
EndStructure

Procedure Is64Bit()
  Protected bIsWow64.l = #False, fnIsWow64Process

  fnIsWow64Process = GetProcAddress_(GetModuleHandle_("kernel32"), "IsWow64Process")

  If fnIsWow64Process
    If Not CallFunctionFast(fnIsWow64Process, GetCurrentProcess_(), @bIsWow64)
    EndIf
  EndIf

  ProcedureReturn bIsWow64
EndProcedure

Procedure.s GetImageName(PID)
  Protected IName$
  Protected *dfn
  Protected hProc

  OpenLibrary(0, "psapi.dll")
  IName$ = Space(#MAX_PATH)

  CompilerIf #PB_Compiler_Unicode
    *dfn = GetFunction(0, "GetProcessImageFileNameW")
  CompilerElse
    *dfn = GetFunction(0, "GetProcessImageFileNameA")
  CompilerEndIf

  hProc = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, PID)
  CallFunctionFast(*dfn, hProc, @IName$, #MAX_PATH)

  ProcedureReturn IName$
EndProcedure

Procedure Find_PB_TrayIcons()
  Protected n
  Protected hwnd
  Protected hTray
  Protected dwExplorerThreadId
  Protected dwExplorerProcessId
  Protected hProc
  Protected *lpData
  Protected *lpRect
  Protected i
  Protected hIcon
  Protected uID
  Protected iState
  Protected IName$
  Protected x
  Protected Position

  If Is64Bit()
    Dim button_td2.TRAYDATA_wow64(20)
    Dim button2.TBBUTTON_wow64   (20)
  Else
    Dim button_td.TRAYDATA(20)
    Dim button.TBBUTTON   (20)
  EndIf

  For n = 1 To 2
    If n = 1
      hWnd = FindWindow_("Shell_TrayWnd", #Null)
      If hWnd
        hWnd = FindWindowEx_(hWnd, #Null, "TrayNotifyWnd", #Null)
        If hWnd
          hWnd = FindWindowEx_(hWnd,#Null, "SysPager", #Null)
          If hWnd
            hTray = FindWindowEx_(hWnd, #Null, "ToolbarWindow32", #Null)
          Else
            ProcedureReturn 0
          EndIf
        Else
          ProcedureReturn 0
        EndIf
      Else
        ProcedureReturn 0
      EndIf
      count = SendMessage_(hTray, #TB_BUTTONCOUNT, 0, 0)
    ElseIf n = 2
      hWnd = FindWindow_("NotifyIconOverflowWindow", #Null)
      If hWnd
        hTray = FindWindowEx_(hWnd, #Null, "ToolbarWindow32", #Null)
      Else
        ProcedureReturn 0
      EndIf
      count = count + SendMessage_(hTray, #TB_BUTTONCOUNT, 0, 0)
    EndIf

    dwExplorerThreadId=GetWindowThreadProcessId_(hTray, @dwExplorerProcessId)
    hProc = OpenProcess_(#PROCESS_ALL_ACCESS, #False, dwExplorerProcessId)

    If Is64Bit()
      *lpData = VirtualAllocEx_(hProc, #Null, SizeOf(TBBUTTON_wow64)*count, #MEM_COMMIT, #PAGE_READWRITE)
    Else
      *lpData = VirtualAllocEx_(hProc, #Null, SizeOf(TBBUTTON)*count, #MEM_COMMIT, #PAGE_READWRITE)
    EndIf

    *lpRect = VirtualAllocEx_(hProc, #Null, SizeOf(RECT)*count, #MEM_COMMIT, #PAGE_READWRITE)

    For i = 0 To count - 1
      If Is64Bit()
        SendMessage_(hTray, #TB_GETBUTTON, i, *lpData+i*SizeOf(TBBUTTON_wow64) )
        ReadProcessMemory_(hProc, *lpData+(i*SizeOf(TBBUTTON_wow64)), @button2.TBBUTTON_wow64(i), SizeOf(TBBUTTON_wow64), #Null)
        ReadProcessMemory_(hProc, button2(i)\dwData, @button_td2.TRAYDATA_wow64(i), SizeOf(TRAYDATA_wow64), #Null)

        hIcon = button_td2.TRAYDATA_wow64(i)\hIcon
        hWnd = button_td2.TRAYDATA_wow64(i)\hwnd
        uID = button_td2.TRAYDATA_wow64(i)\uID
        iState = button2.TBBUTTON_wow64(i)\fsState
        IName$ = GetImageName(uID)

        If Trim(IName$) = ""
          IName$ = "System Icon"
        Else
          For x = 1 To 3
            Position = FindString(IName$,"\",Position+1)
          Next

          IName$ = Right(IName$,Len(IName$)-Position)

          For x = 0 To HDN
            IName$ = HDname$(x)+IName$
            If FileSize(IName$) > 0
              Break
            EndIf
          Next
        EndIf

        If n = 1
          turn = i
          STray$(turn) = "     " + Str(hIcon) +  Chr(10) + Str(hWnd) + Chr(10) + Str(iState) + Chr(10) + Str(uID) + Chr(10) + IName$
        Else
          turn = turn + 1
          STray$(turn) = "     " + Str(hIcon) +  Chr(10) + Str(hWnd) + Chr(10) + "OFN" + Chr(10) + Str(uID) + Chr(10) + IName$
        EndIf

        Icon(turn) = hIcon
      Else
        SendMessage_(hTray, #TB_GETBUTTON, i, *lpData+i*SizeOf(TBBUTTON) )
        ReadProcessMemory_(hProc, *lpData+(i*SizeOf(TBBUTTON)), @button.TBBUTTON(i), SizeOf(TBBUTTON), #Null)
        ReadProcessMemory_(hProc, button(i)\dwData, @button_td.TRAYDATA(i), SizeOf(TRAYDATA), #Null)

        hIcon = button_td.TRAYDATA(i)\hIcon
        hWnd = button_td.TRAYDATA(i)\hwnd
        uID = button_td.TRAYDATA(i)\uID
        iState = button.TBBUTTON(i)\fsState
        IName$ = GetImageName(uID)

        If Trim(IName$) = ""
          IName$ = "System Icon"
        Else
          For x = 1 To 3
            Position = FindString(IName$,"\",Position+1)
          Next

          IName$ = Right(IName$,Len(IName$)-Position)

          For x = 0 To HDN
            IName$ = HDname$(x)+IName$
            If FileSize(IName$) > 0
              Break
            EndIf
          Next
        EndIf

        If n = 1
          turn = i
          STray$(turn) = "     " + Str(hIcon)  + Chr(10) + Str(hWnd) + Chr(10) + Str(iState) + Chr(10) + Str(uID) + Chr(10) + IName$
        Else
          turn = turn + 1
          STray$(turn) = "     " + Str(hIcon)  + Chr(10) + Str(hWnd) + Chr(10) + "OFN" + Chr(10) + Str(uID) + Chr(10) + IName$
        EndIf

        Icon(turn) = hIcon

      EndIf

    Next

  Next

  VirtualFreeEx_(hProc, *lpData, #Null, #MEM_RELEASE)
  VirtualFreeEx_(hProc, *lpRect, #Null, #MEM_RELEASE)
  CloseHandle_(hProc)

EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0,10,10,780,580,"Icon-Icon Handle", 100, #PB_ListIcon_GridLines)
  SetGadgetColor(0, #PB_Gadget_FrontColor, $FD4B0B)
  SetGadgetColor(0, #PB_Gadget_BackColor, $E8FEFE)

  AddGadgetColumn(0, 1, "Win Handle", 80)
  AddGadgetColumn(0, 2, "Status", 45)
  AddGadgetColumn(0, 3, "PID", 50)
  AddGadgetColumn(0, 4, "Image name", 500)

  Find_PB_TrayIcons()

  For x = 0 To count-1
    AddGadgetItem(0,-1, STray$(x), Icon(x))
  Next

  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      End
    EndIf
  ForEver
EndIf
searched for the Find_PB_TrayIcons function, found another link, link
BarryG
Addict
Addict
Posts: 4168
Joined: Thu Apr 18, 2019 8:17 am

Re: How to detect apps running in the system tray?

Post by BarryG »

Thanks for the links, AZJIO!

This is the one that does what I need -> viewtopic.php?t=51549

It shows the exe name of each system tray icon, which is what I'm after. Much appreciated!
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: [Solved] How to detect apps running in the system tray?

Post by netmaestro »

; Author: NM, RASHAD
I've been compressed! I only hope it was lossless...
BERESHEIT
Post Reply