?
Solved

How can I enumerate SysTray / Taskbar Notification Area icons in 64-bit Windows versions?

Posted on 2009-04-29
12
Medium Priority
?
2,601 Views
Last Modified: 2013-12-20
Dear Experts,

I need a safe way for a VB6 app to check whether a certain icon in the taskbar notification area exists. There are lots of solutions that work in Windows 32-bit versions but fail on XP64 and Vista64. I have tried to adjust the TRAYDATA and TBBUTTON structures to match 64-bit padding as proposed by MSDN but still the only thing I can get is the number of tray icons. Whenever I try to loop the icons found, I get nothing but zeroes when using SendMessage(hwnd, TB_GETBUTTON, index, addrPtr). The function returns 0 which I think is the same as FALSE. The addrPtr is the one I got from the previous VirtualAlloc call which successfully reserved the space needed for the TBBUTTON structure (24 bytes). GetLastError returns a zero for the said SendMessage call all the same so I don't know what I'm doing wrong. The code works fine on Win32 (2000 / XP / Vista) though.

So, can anyone tell me what to do enumerate the icons on Win64? All I need is the process name and maybe the ID field. The solution should also work with Vista UAC enabled.

Below I have attached the source code I'm using.

Thanks in advance!
Regards
MunichJoe2009
--- to run this code, create a new standard VB6 project, add a CommandButton (Command1), a PictureBox (Picture1) and a ListBox (List1). Then go to the form's source code and paste the following:
 
Option Explicit
 
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Function GetLastError Lib "kernel32.dll" () As Long
 
' ------------ 64 bit recognition
 
Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32.dll" (ByVal hLibModule As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32.dll" () As Long
Private Declare Function IsWow64Process Lib "kernel32.dll" (ByVal hProcess As Long, ByRef Wow64Process As Long) As Long
 
' ------------
 
Private Const PROCESS_QUERY_INFORMATION     As Long = 1024
Private Const PROCESS_ALL_ACCESS            As Long = &H1F0FFF
Private Const PROCESS_VM_READ               As Long = &H10
Private Const MEM_COMMIT                    As Long = &H1000
Private Const MEM_RELEASE                   As Long = &H8000
Private Const PAGE_READONLY                 As Long = &H2
Private Const PAGE_READWRITE                As Long = &H4
Private Const WM_USER                       As Long = &H400
Private Const TB_BUTTONCOUNT                As Long = (WM_USER + 24)
Private Const TB_GETBUTTON                  As Long = (WM_USER + 23)
Private Const TBSTATE_HIDDEN                As Long = &H8
Private Const DI_MASK                       As Long = &H1
Private Const DI_IMAGE                      As Long = &H2
 
Private Type TRAYDATA
  hwnd          As Long
  uID           As Long
  uCallback     As Long
  Reserved1     As Long
  Reserved2     As Long
  hIcon         As Long
End Type
 
Private Type TBBUTTON
  iBitmap      As Long
  idCommand    As Long
  fsState      As Byte
  fsStyle      As Byte
  bReserved1   As Byte
  bReserved2   As Byte
  dwData       As Long
  iString      As Long
End Type
 
Private Type TBBUTTON64
  iBitmap      As Long
  idCommand    As Long
  fsState      As Byte
  fsStyle      As Byte
  bReserved1   As Byte
  bReserved2   As Byte
  bReserved3   As Byte
  bReserved4   As Byte
  bReserved5   As Byte
  bReserved6   As Byte
  dwData       As Long
  iString      As Long
End Type
 
Private Declare Function FindWindowW Lib "user32" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long
Private Declare Function FindWindowExW Lib "user32" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As Long, ByVal lpsz2 As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetModuleFileNameExW Lib "Psapi.dll" (ByVal hProcess As Long, ByVal hModule As Long, ByVal lpFileName As Long, ByVal nSize As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cbCopy As Long)
Private Declare Function DrawIconEx Lib "user32" (ByVal hdc As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
Private Declare Function ExtractIconA Lib "shell32" (ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long
 
Public Function GetProcessNameFromhWnd(ByVal dwhWnd As Long) As String
 
  ' Returns process name from hwnd.
  
  Dim Buffer(1024 - 1)  As Byte
  Dim hProcess          As Long
  Dim ThreadId          As Long
  Dim Pid               As Long
  Dim cbLen             As Long
  
  Call OutputDebugString("GetProcessNameFromHWnd for 0x" & Hex(dwhWnd))
  ThreadId = GetWindowThreadProcessId(dwhWnd, Pid)
  Call OutputDebugString("  ThreadID = " & Hex(ThreadId))
  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, Pid)
  Call OutputDebugString("  hProcess = " & Hex(hProcess))
  cbLen = GetModuleFileNameExW(hProcess, 0, VarPtr(Buffer(0)), UBound(Buffer))
  Call OutputDebugString("  cbLen = " & cbLen)
  GetProcessNameFromhWnd = Left$(Buffer, cbLen)
  Call OutputDebugString("  Buffer = " & GetProcessNameFromhWnd)
  CloseHandle hProcess
  Erase Buffer
  
  
End Function
    
Public Sub GetTrayWindowInfo()
 
  Dim tb            As TBBUTTON
  Dim tray          As TRAYDATA
  Dim ThreadId        As Long
  Dim hProcess        As Long
  Dim AddrPtr         As Long
  Dim AddrPtr2        As Long
  Dim Pid             As Long
  Dim cb              As Long
  Dim cbRead          As Long
  Dim TrayCount       As Long
  Dim hWindow         As Long
  Dim szName          As String
  Dim IconPos         As Long
  Dim hIcon           As Long
  
  ' * Get the tray window handle. ( Window XP).
  hWindow = FindWindowW(StrPtr("Shell_TrayWnd"), 0)
  hWindow = FindWindowExW(hWindow, 0, StrPtr("TrayNotifyWnd"), 0)
  hWindow = FindWindowExW(hWindow, 0, StrPtr("SysPager"), 0)
  hWindow = FindWindowExW(hWindow, 0, StrPtr("ToolbarWindow32"), 0)
  
  ' * Get the count of buttons in tray window.
  TrayCount = SendMessage(hWindow, TB_BUTTONCOUNT, 0, 0)
 
  ' Allocate memory
  ThreadId = GetWindowThreadProcessId(hWindow, Pid)
  hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, Pid)
  AddrPtr = VirtualAllocEx(hProcess, 0, LenB(tray), MEM_COMMIT, PAGE_READONLY)
  AddrPtr2 = AddrPtr
 
  ' Read information into TBUTTON
  For cb = 0 To TrayCount - 1
  
    SendMessage hWindow, TB_GETBUTTON, cb, AddrPtr2
    ReadProcessMemory hProcess, AddrPtr2, tb, LenB(tb), cbRead
    ReadProcessMemory hProcess, ByVal tb.dwData, tray, LenB(tray), cbRead
    
    ' Check if the button is hidden and only show visible tray buttons.
    'If tb.fsState <> TBSTATE_HIDDEN Then
    ' Get the process associated with the button.
      szName = GetProcessNameFromhWnd(tray.hwnd)
    ' Add the process location to a listbox
      List1.AddItem szName & " R1:" & Hex(tb.bReserved1) & " R2:" & Hex(tb.bReserved2) & " IDCMD:" & Hex(tb.idCommand) & " IS:" & Hex(tb.iString) & " D:" & Hex(tb.dwData)
    ' Use Tray.hIcon to attemp to draw icon into picture box.
      If DrawIconEx(Picture1.hdc, IconPos, 0, tray.hIcon, 16, 16, 0, 0, DI_MASK Or DI_IMAGE) = False Then
    ' If the Tray.hIcon is invalid try to extract the first icon instead.
        hIcon = ExtractIconA(0, szName, 0)
        Call DrawIconEx(Picture1.hdc, IconPos, 0, hIcon, 16, 16, 0, 0, DI_MASK Or DI_IMAGE)
        DestroyIcon hIcon
      End If
      ' Move the icon position for next icon in pictureBox
      IconPos = IconPos + 16
    'End If
    
  Next cb
  
  ' * Cleanup
  VirtualFreeEx hProcess, AddrPtr, 0, MEM_RELEASE
  CloseHandle hProcess
     
End Sub
 
Public Sub GetTrayWindowInfo64()
 
    Dim tb As TBBUTTON64
    Dim tray As TRAYDATA
    Dim ThreadId As Long
    Dim hProcess As Long
    Dim AddrPtr As Long
    Dim AddrPtr2 As Long
    Dim Pid As Long
    Dim cb As Long
    Dim cbRead As Long
    Dim TrayCount As Long
    Dim hWindow As Long
    Dim szName As String
    Dim IconPos As Long
    Dim hIcon As Long
    Dim lResult As Long
    Dim lErr As Long
    
    ' * Get the tray window handle. ( Window XP).
    hWindow = FindWindowW(StrPtr("Shell_TrayWnd"), 0)
    hWindow = FindWindowExW(hWindow, 0, StrPtr("TrayNotifyWnd"), 0)
    hWindow = FindWindowExW(hWindow, 0, StrPtr("SysPager"), 0)
    hWindow = FindWindowExW(hWindow, 0, StrPtr("ToolbarWindow32"), 0)
    
    Call OutputDebugString("ToolbarWindow32 hwnd = " & Hex(hWindow))
    
    ' * Get the count of buttons in tray window.
    TrayCount = SendMessage(hWindow, TB_BUTTONCOUNT, 0, 0)
    Call OutputDebugString("found " & TrayCount & " tray icon entries")
 
    ' Allocate memory
    ThreadId = GetWindowThreadProcessId(hWindow, Pid)
    Call OutputDebugString("threadid is " & Hex(ThreadId))
    Call OutputDebugString("pid is " & Pid)
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, Pid)
    Call OutputDebugString("hprocess is " & Hex(hProcess))
    If hProcess <> 0 Then
    
        AddrPtr = VirtualAllocEx(hProcess, 0&, LenB(tray), MEM_COMMIT, PAGE_READONLY)
        Call OutputDebugString("addrptr is " & Hex(AddrPtr) & ", allocated " & LenB(tray) & " bytes")
        
        If AddrPtr <> 0 Then
            AddrPtr2 = AddrPtr
            
            ' Read information into TBUTTON
            For cb = 0 To TrayCount - 1
                lResult = SendMessage(hWindow, TB_GETBUTTON, cb, AddrPtr2)
                Call OutputDebugString("sendMsg TB_GETBUTTON for " & cb & " returns 0x" & Hex(lResult) & ", addrptr2 = " & Hex(AddrPtr2))
                If lResult <> 0 Then
                    lResult = ReadProcessMemory(hProcess, AddrPtr2, tb, LenB(tb), cbRead)
                    Call OutputDebugString("ReadProcMem1 returns 0x" & Hex(lResult) & ", cbread = " & cbRead & ", len = " & LenB(tb))
                    Call OutputDebugString("    dwData = " & Hex(tb.dwData))
                    Call OutputDebugString("    fsstate = " & Hex(tb.fsState))
                    Call OutputDebugString("    fsstyle = " & Hex(tb.fsStyle))
                    Call OutputDebugString("    ibitmap = " & Hex(tb.iBitmap))
                    Call OutputDebugString("    idcommand = " & Hex(tb.idCommand))
                    Call OutputDebugString("    istring = " & Hex(tb.iString))
                    
                    lResult = ReadProcessMemory(hProcess, ByVal tb.dwData, tray, LenB(tray), cbRead)
                    Call OutputDebugString("ReadProcMem2 returns 0x" & Hex(lResult) & ", cbread = " & cbRead & ", len = " & LenB(tb))
                    Call OutputDebugString("    tray hicon = " & Hex(tray.hIcon))
                    Call OutputDebugString("    tray hwnd = " & Hex(tray.hwnd))
                    Call OutputDebugString("    tray ucallback = " & Hex(tray.uCallback))
                    Call OutputDebugString("    tray uid = " & Hex(tray.uID))
                    Call OutputDebugString("ReadProcMem2 returns 0x" & Hex(lResult))
                    
                    ' Check if the button is hidden and only show visible tray buttons.
                    'If tb.fsState <> TBSTATE_HIDDEN Then
                    ' Get the process associated with the button.
                        szName = GetProcessNameFromhWnd(tray.hwnd)
                    ' Add the process location to a listbox
                        List1.AddItem szName & " IDCMD:" & Hex(tb.idCommand) & " IS:" & Hex(tb.iString) & " D:" & Hex(tb.dwData)
                    ' Use Tray.hIcon to attemp to draw icon into picture box.
                        If DrawIconEx(Picture1.hdc, IconPos, 0, tray.hIcon, 16, 16, 0, 0, DI_MASK Or DI_IMAGE) = False Then
                    ' If the Tray.hIcon is invalid try to extract the first icon instead.
                            hIcon = ExtractIconA(0, szName, 0)
                            Call DrawIconEx(Picture1.hdc, IconPos, 0, hIcon, 16, 16, 0, 0, DI_MASK Or DI_IMAGE)
                            DestroyIcon hIcon
                        End If
                        ' Move the icon position for next icon in pictureBox
                        IconPos = IconPos + 16
                    'End If
                 Else
                         lErr = GetLastError
                         Call OutputDebugString("LastError = 0x" & Hex(lErr))
                 End If
             Next cb
             
             ' * Cleanup
             VirtualFreeEx hProcess, AddrPtr, 0, MEM_RELEASE
        
        End If
        CloseHandle hProcess
            
    End If
         
End Sub
 
Private Sub Command1_Click()
 
    If Is64BitOS Then
        Call OutputDebugString("64-bit path")
        Call GetTrayWindowInfo64
    Else
        Call GetTrayWindowInfo
    End If
    
End Sub
 
Public Property Get Is64BitOS() As Boolean
 
    Dim hMod As Long
    Dim lIsWow64Process As Long
    
    hMod = LoadLibrary("kernel32.dll")
    
    If CBool(GetProcAddress(hMod, "IsWow64Process")) Then
        If CBool(IsWow64Process(GetCurrentProcess(), lIsWow64Process)) Then
            Is64BitOS = CBool(lIsWow64Process)
        End If
    End If
    
    FreeLibrary hMod
    
End Property

Open in new window

0
Comment
Question by:MunichJoe2009
  • 5
  • 5
10 Comments
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 24285033
I don't have a copy of 64 editions installed or I might be able to debug it but because I don't I can only suggest that you check the following.

The first thing you need to check is if the toolbar windows are still the same as 32 bit versions and confirm that the window handle is correct on 64.

hWindow = FindWindowW(StrPtr("Shell_TrayWnd"), 0)
etc...
etc..
etc..

Second step would be to check if the process handle returned is valid.
Please debug the below line and check to see that you are getting a valid process handle.

hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, Pid)

0
 

Author Comment

by:MunichJoe2009
ID: 24285282
Dear egl1044,

the debug output shows that the ToolbarWindow32 is actually found, so generally this should not be an issue. The output also proves that the hProcess gets a value. UAC is currently disabled, I guess that this would fail once UAC becomes enabled again.
I think that the actual problem is the SendMessage (TB_GETBUTTON) command which seems to return invalid data. The icons are enumerated but no useful data is drawn from them, probably due to something I need to change in the type declarations for TRAYDATA and / or TBBUTTON64. So far, I don't know any product (commercial or free) that can do this. I have checked these:

All work fine with 32-bit though.

Regards,
MunichJoe2009




0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 24293934
I had some time to install a copy of x64 XP and debug the code. I was succesful in obtaining the hwnd member however GetModuleFileNameExW seems to fail on anything that is running as 64 bit but GetProcessImageFileNameW seems to work fine.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 29

Accepted Solution

by:
nffvrxqgrcfqvvc earned 1500 total points
ID: 24294252
The following is working fine for me on xp 64 os.

Add 1 command button
Add 1 listbox
Option Explicit
 
' List system tray icons 64 bit os.
 
Private Const PROCESS_ALL_ACCESS    As Long = &H1F0FFF
Private Const PAGE_READWRITE        As Long = &H4
Private Const MEM_COMMIT            As Long = &H1000
Private Const MEM_RELEASE           As Long = &H8000
Private Const WM_USER               As Long = &H400
Private Const TB_BUTTONCOUNT        As Long = (WM_USER + 24)
Private Const TB_GETBUTTON          As Long = (WM_USER + 23)
 
Private Type TBBUTTON64
  iBitmap      As Long
  idCommand    As Long
  fsState      As Byte
  fsStyle      As Byte
  Padding1     As Byte
  Padding2     As Byte
  Padding3     As Byte
  Padding4     As Byte
  Padding5     As Byte
  Padding6     As Byte
  dwData       As Long
  iString      As Long
End Type
 
Private Declare Function FindWindowW Lib "user32" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long
Private Declare Function FindWindowExW Lib "user32" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As Long, ByVal lpsz2 As Long) As Long
Private Declare Function SendMessageA Lib "user32" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, ByRef lpdwProcessId As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Long, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
' Kernel32.lib on Windows 7 and Windows Server 2008 R2
Private Declare Function GetProcessImageFileNameWin7 Lib "kernel32" Alias "GetProcessImageFileNameW" (ByVal hProcess As Long, ByVal lpImageFileName As Long, ByVal nSize As Long) As Long
' Psapi.lib on Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP/2000
Private Declare Function GetProcessImageFileNameW Lib "psapi" (ByVal hProcess As Long, ByVal lpImageFileName As Long, ByVal nSize As Long) As Long
 
Private Function GetProcessNameByhWnd(ByVal dwhWnd As Long) As String
 
' helper function returns a process name from an hwnd.(XP +)
 
  Dim pBuffer(4096) As Byte
  Dim dwProcess     As Long
  Dim dwPid         As Long
  Dim dwThread      As Long
  Dim cb            As Long
  
  dwThread = GetWindowThreadProcessId(dwhWnd, dwPid)
  dwProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid)
  cb = GetProcessImageFileNameW(dwProcess, VarPtr(pBuffer(0)), 4096)
  
  If cb <> 0 Then
      GetProcessNameByhWnd = Left$(pBuffer, cb)
    Else
      GetProcessNameByhWnd = vbNullString
  End If
  
  Call CloseHandle(dwProcess)
  Erase pBuffer
  
End Function
 
Public Sub ListTray64()
 
  Dim tb64          As TBBUTTON64
  Dim hWindow       As Long
  Dim hProcess      As Long
  Dim ThreadId      As Long
  Dim dwCount       As Long
  Dim lpPid         As Long
  Dim lphWnd        As Long
  Dim lpPointer     As Long
  Dim dwIndex       As Long
  Dim cbRead        As Long
  
  hWindow = FindWindowW(StrPtr("Shell_TrayWnd"), 0)
  hWindow = FindWindowExW(hWindow, 0, StrPtr("TrayNotifyWnd"), 0)
  hWindow = FindWindowExW(hWindow, 0, StrPtr("SysPager"), 0)
  hWindow = FindWindowExW(hWindow, 0, StrPtr("ToolbarWindow32"), 0)
  
  ' returns the count of system tray buttons.
  dwCount = SendMessageA(hWindow, TB_BUTTONCOUNT, 0, 0)
  ' pointer to a process id from an hwnd.
  ThreadId = GetWindowThreadProcessId(hWindow, lpPid)
  ' real process handle from process id.
  hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, lpPid)
  ' allocate memory from out of process
  lpPointer = VirtualAllocEx(hProcess, 0, Len(tb64), MEM_COMMIT, PAGE_READWRITE)
  ' enumerate the tray icons.
  For dwIndex = 0 To dwCount - 1
 
    Call SendMessageA(hWindow, TB_GETBUTTON, dwIndex, ByVal lpPointer)
    
    If ReadProcessMemory(hProcess, ByVal lpPointer, ByVal VarPtr(tb64), Len(tb64), cbRead) Then
      If tb64.dwData <> 0 Then
        ' The first 4 bytes is the hWnd.
        Call ReadProcessMemory(hProcess, ByVal tb64.dwData, lphWnd, 4, cbRead)
          List1.AddItem GetProcessNameByhWnd(lphWnd)
      End If
    End If
    
  Next dwIndex
  
  ' free memory and cleanup
  Call VirtualFreeEx(hProcess, lpPointer, 0, MEM_RELEASE)
  Call CloseHandle(hProcess)
  
End Sub
 
 
Private Sub Command1_Click()
 
  Call ListTray64
 
End Sub

Open in new window

0
 

Author Comment

by:MunichJoe2009
ID: 24294275
Dear egl1044,

sounds great! I will test your solution asap. Are you sure this also works with UAC enabled? I'm not sure if UAC will let an application perform cross-process memory access as is needed here without nagging the user first...

Thank you very much! I will let you know about my tests.
Regards,

MunichJoe2009
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 24294469
The users will need to run the code as an administrator so if UAC is enabled you can have a look at this recent question. http:Q_24243720.html

The above will tell you if the process token is running with the administrator session and not the user session even if the user is administrator the session is a standard user so it's basically (IsProcessRunningAsAdmin).
0
 

Author Comment

by:MunichJoe2009
ID: 24294629
So I understand that the above code works only if my application has requested elevated privileges right from the start, unless UAC was turned off completely?
I'm a little worried about users losing confidence in the product if now it wants to be run as admin which was never needed in previous versions...
I am not very familiar with UAC yet. Is there a way to tell UAC that the product is automatically run as admin and needs no user interaction? Maybe a signature or something that UAC recognizes as trusted? And, to make things worse, can I do this with a VB6 executable?
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 24294813
I have just tested on a limited account and it worked. :) However because of the PROCESS_ALL_ACCESS flag you may run into problems when trying to obtain a process handle under standard user account if a process has a denied ace getting a process handle will fail and you wont return a process name. Thats not a big problem but because you need Administrator rights to enable SeDebugPrivileges which grants you all access to process handle to ensure you can return any process name. You can test this by trying to use the function on a process which restricts specific rights.
0
 

Author Comment

by:MunichJoe2009
ID: 24295228
Thanks once again egl1044, I will let you know if this solves my problem. This was a great help!
0
 

Author Closing Comment

by:MunichJoe2009
ID: 31575857
The solution can return the names of processes who registered systray icons but not the tray icon data associated. Anyway this is perfect for me for a start. Thank you!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Know the reasons and solutions to move/import EDB to New Exchange Server. Also, find out how to recover an Exchange .edb file and to restore the file back.
MS Outlook undoubtedly is the most widely used email client.Its user-friendliness, cost effectiveness, and availability with Microsoft Office Suite make it the most popular email application.  Its compatibility with Microsoft applications like Exch…
The viewer will learn how to successfully create a multiboot device using the SARDU utility on Windows 7. Start the SARDU utility: Change the image directory to wherever you store your ISOs, this will prevent you from having 2 copies of an ISO wit…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Suggested Courses

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question