Jump to content
Mbee

[Solved] New "sys tray" access problems under Windows 10

Recommended Posts

Mbee

One of my GUI applications requires that a particular third-party application not only be running, but be present in the "sys tray" (aka Taskbar). When this 3p app is active but not in the systray/taskbar, it is not ready for proper use, and I must inform the user about this.

Here is a code snippet that used to work fine under Windows 7:

;
; #FUNCTION# =========================================================================================================
; Name...........: _Get_Systray_BtnIndex
; Description ...: Determines if an appllication with the specified title is running in the Systen Tray
;                   and if so, returns the relative index number of it's button on the tray.
; Syntax.........: _Get_Systray_BtnIndex($iTitleText)
; Parameters ....: $iTitleText  -> The (tool-tip) title of the desired application
; Return values .: Success - Returns the index number of the desired appliction button, 1 being the first
;                  Failure - Returns 0 if desired application is not found in the System Tray
;                             Sets @error as follows:
;                                0:  Normal return
;                               -1: System Tray was empty (i.e., no appllications running the tray)
;                               -2: No System Tray was found
; Remarks .......; Setting any parameter to -1 leaves the current value unchanged
;                  Setting the $iStyle parameter to 'Default' resets ALL parameters to default values <<<<<<<<<<<<<<<<<<<<<<<
;                  Setting any other parameter to "Default" only resets that parameter
; Author ........: Poster "war59312", and code was found at URL:
;                       http://www.autoitscript.com/forum/topic/40550-check-if-program-is-running-under-system-tray/#entry902746
;                   Modified by mjb on 26-June-2014 to return @extended error code rather than using MsgBox() to report errors.
;
Func _Get_Systray_BtnIndex($sToolTipTitle)
    ; Find systray handle
    Local $hSysTray_Handle = ControlGetHandle('[Class:Shell_TrayWnd]', '', '[Class:ToolbarWindow32;Instance:1]')
    If @error Then
        Return SetError( -2, 0, 0 )
    EndIf

    ; Get systray item count
    Local $iSystray_ButCount = _GUICtrlToolbar_ButtonCount($hSysTray_Handle)
    If $iSystray_ButCount = 0 Then
        Return SetError( -1, 0 , 0 )
    EndIf

    ; Look for wanted tooltip
    For $iSystray_ButtonNumber = 0 To $iSystray_ButCount - 1
        If StringInStr(_GUICtrlToolbar_GetButtonText($hSysTray_Handle, $iSystray_ButtonNumber), $sToolTipTitle) > 0 Then ExitLoop
    Next

    If $iSystray_ButtonNumber = $iSystray_ButCount Then
        Return 0                        ; Desired application is NOT running in the System Tray
    Else
        Return $iSystray_ButtonNumber   ; Application was found in the SysTray
    EndIf
EndFunc     ;==> _Get_Systray_BtnIndex
;

 

But what's happening under Windows 10 is that the "_GUICtrlToolbar_ButtonCount()" always returns 1, even though there are 10-14 items visible in the Task Bar.  Unsurprisingly, the single item returned has nothing to do with the 3'rd party application in question.

As you probably know, Microsoft made significant changes to the systray/taskbar since Windows 7 (or at least by Windows 10). I spent quite a while searching MSDN for some other way to accomplish what I need, but I must be too stupid to figure it out.

Please help.   Thanks!

 

Edited by Mbee

Share this post


Link to post
Share on other sites
BrewManNH

You're not looking in the NotifyIconOverflowWindow window for more icons.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
Mbee
6 hours ago, BrewManNH said:

You're not looking in the NotifyIconOverflowWindow window for more icons.

Thanks for your reply, but I'm afraid I have no idea how to do that.  Can you tell me, please?

I looked around for help, and I found and then tried using the "Systray UDF" by @tuapeand modified by @Erik Pilsits posted here: _systray udf.

I chose it because if you set the $iWin parameter to 2, apparently the suggestion is that it is supposed to "look in the NotifyIconOverflowWindow for more icons".  But when I call "_SysTrayIconCount(2)", it always returns zero icons even though there are actually 10-14.

Please advise.  Thanks!

Share this post


Link to post
Share on other sites
AutoBert

Run this small example:

#include <Array.au3>
#include <GuiToolBar.au3>

$sSearchtext='Lautsprecher: 100%'   ;change to your needs
$iButton=Get_SysTray_IconText($sSearchtext)
MsgBox (64,'Searched Button','Button: '&$iButton&@CRLF&'Instance: '&@extended)

Func Get_SysTray_IconText($sSearch)
    Local $hSysTray_Handle
    For $i = 1 To 99
        ; Find systray handles
        $hSysTray_Handle = ControlGetHandle('[Class:Shell_TrayWnd]', '', '[Class:ToolbarWindow32;Instance:' & $i & ']')
        If @error Then
            ;MsgBox(16, "Error", "System tray not found")
            ExitLoop
        EndIf

        ; Get systray item count
        Local $iSysTray_ButCount = _GUICtrlToolbar_ButtonCount($hSysTray_Handle)
        If $iSysTray_ButCount = 0 Then
            ;MsgBox(16, "Error", "No items found in system tray")
            ContinueLoop
        EndIf

        Local $aSysTray_ButtonText[$iSysTray_ButCount]

        ; Look for wanted tooltip
        For $iSysTray_ButtonNumber = 0 To $iSysTray_ButCount - 1
            If $sSearch= _GUICtrlToolbar_GetButtonText($hSysTray_Handle, $iSysTray_ButtonNumber) Then _
            Return SetError(0, $i, $iSysTray_ButtonNumber)
        Next
    Next
    Return SetError(1, -1, -1)

EndFunc   ;==>Get_SysTray_IconText


Exit

it returns:

  • succes: the ButtonNumber and in @extended the instance of the toolbarwindow.
  • failur: -1 @error -1 and @extended -1
  • Like 1

Share this post


Link to post
Share on other sites
BrewManNH

Try this, it looks at both the visible system tray icons and the overflow (hidden) icons.

#include <GuiToolBar.au3>

Sleep(1000)
MsgBox(0, "", Get_SysTray_IconCount())

Func Get_SysTray_IconCount() ; http://www.autoitscript.com/forum/topic/157933-hinttray-tip-how-to-get-text/?p=1145366

    ; Find systray handle for "User Promoted Notification Area"
    Local $hSysTray_Handle = ControlGetHandle('[Class:Shell_TrayWnd]', '', '[Class:ToolbarWindow32;Instance:1]')
    If @error Then
        MsgBox(16, "Error", "System tray not found")
    EndIf
    ; Find systray handle for "Overflow Notification Area" i.e. hidden icons
    Local $hSysTray_Handle_Hidden = ControlGetHandle('[Class:NotifyIconOverflowWindow]', '', '[Class:ToolbarWindow32;Instance:1]')
    If @error Then
        MsgBox(16, "Error", "Overflow Notification Area not found")
    EndIf

    ; Get systray icon count
    Local $iSysTray_ButCount = _GUICtrlToolbar_ButtonCount($hSysTray_Handle)
    If $iSysTray_ButCount = 0 Then
        MsgBox(16, "Error", "No items found in system tray")
        Return ""
    EndIf

    ; Get hidden systray icon count

    $iSysTray_ButCount += _GUICtrlToolbar_ButtonCount($hSysTray_Handle_Hidden)

    Return $iSysTray_ButCount

EndFunc   ;==>Get_SysTray_IconCount

 


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
Mbee

Thanks to you both for trying to help me out!!

@AutoBert: I got the failure return from your test code: Button -1  and Instance -1.

@BrewManNH: The output was only 1, which is way wrong.  So it appears the Overflow didn't count after all.

 

If it matters (and for all I know it does), I've tweaked my Win 10 Pro settings. For example, I'm using the Classic start menu and Classic Explorer settings, and I've used two different Win 10 tweakers: (1): WinAero tweaker and (2): Ultimate Windows Tweaker v4.2.1

I'm about to try the two tests again with the Classic stuff disabled.  If the results are any different, I'll post back to let you both know.

Thanks again!

Share this post


Link to post
Share on other sites
Mbee

Well, even though I said I'd post if I got different results with all the Classic stuff disabled, I figured I'd post to confirm that there were no differences.  I got the same erroneous results...

Share this post


Link to post
Share on other sites
BrewManNH

The script I posted showed me that I had 13 icons. This is on Windows 10, Enterprise x64. The script works, you're doing something wrong, or one of the programs you're using is causing it to fail.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
Mbee
15 minutes ago, BrewManNH said:

The script I posted showed me that I had 13 icons. This is on Windows 10, Enterprise x64. The script works, you're doing something wrong, or one of the programs you're using is causing it to fail.

Well, I figured it out...  What I did was to use Au3Info_x64 and then pointed to the systray/taskbar.  It turned out that "[Class:ToolbarWindow32;Instance:1]" was irrelevant and had an incorrect count.  However, Instance:2 showed all 14 taskbar items!

@AutoBert's code correctly covered all instances, and so it would have worked fine except for my mistake, which was that I didn't enter the full exactly correct string for his "$sSearchtext" parameter.  When I revised his code to use a substring search instead of a full exact search, it worked exactly right!

Problem solved.

Thanks again to you both! :)

 

Share this post


Link to post
Share on other sites
AutoBert
51 minutes ago, Mbee said:

@AutoBert's code correctly covered all instances, a

nice to read. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • faustf
      By faustf
      hi guys
      i have a script  like this,  in windows 7 work perfect , in windows 10 not  work  , some one can explain me  why ??'
      #include <Array.au3> #include <MsgBoxConstants.au3> Global $aGPathFoto= FileReadToArray (@ScriptDir & "\TEMP\PathFoto.txt") Local $ctrl = 0 While 1 Local $hWnd = WinWait("[CLASS:#32770]", "", 10) If WinExists("[CLASS:#32770]") Then If $ctrl < 2 Then ControlSend($hWnd, "Choose File to Upload", "[CLASS:Edit; INSTANCE:1]", $aGPathFoto[0]&"{Enter}") Exit $ctrl += 1 Else ExitLoop EndIf EndIf WEnd $aGpathfoto = C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg
    • Skeletor
      By Skeletor
      Hi Virtual People, 
      I'm trying to lock my screen in Windows 10 but to no avail. 
      Has Windows 10 forbidden this feature? 
      Send("#l") Above code does not work. Even sending Ctrl Alt Del does not work nor as an Admin. 
      Note: I want to lock my screen, not log off. Thanks for been kind.
       
    • astrionn
      By astrionn
      Hi Guys,
       
      I`m trying to record with my webcam in 5s intervalls and do some stuff between starting to record and stoping.
      I took code from here: https://www.autoitscript.com/forum/topic/27925-webcam-example/
      and took what looked relevant to me.
      I use 3 different files:
       Is called WMS.au3 and contains all the constants for the dll calls is called rec.au3 and does all necessary dll calls to start a webcam recording to a file Is called stopcam.exe and does the dll calls to stop recording into a file WMS.au3  :
      $WM_CAP_START = 0x400 $WM_CAP_UNICODE_START = $WM_CAP_START +100 $WM_CAP_PAL_SAVEA = $WM_CAP_START + 81 $WM_CAP_PAL_SAVEW = $WM_CAP_UNICODE_START + 81 $WM_CAP_UNICODE_END = $WM_CAP_PAL_SAVEW $WM_CAP_ABORT = $WM_CAP_START + 69 $WM_CAP_DLG_VIDEOCOMPRESSION = $WM_CAP_START + 46 $WM_CAP_DLG_VIDEODISPLAY = $WM_CAP_START + 43 $WM_CAP_DLG_VIDEOFORMAT = $WM_CAP_START + 41 $WM_CAP_DLG_VIDEOSOURCE = $WM_CAP_START + 42 $WM_CAP_DRIVER_CONNECT = $WM_CAP_START + 10 $WM_CAP_DRIVER_DISCONNECT = $WM_CAP_START + 11 $WM_CAP_DRIVER_GET_CAPS = $WM_CAP_START + 14 $WM_CAP_DRIVER_GET_NAMEA = $WM_CAP_START + 12 $WM_CAP_DRIVER_GET_NAMEW = $WM_CAP_UNICODE_START + 12 $WM_CAP_DRIVER_GET_VERSIONA = $WM_CAP_START + 13 $WM_CAP_DRIVER_GET_VERSIONW = $WM_CAP_UNICODE_START + 13 $WM_CAP_EDIT_COPY = $WM_CAP_START + 30 $WM_CAP_END = $WM_CAP_UNICODE_END $WM_CAP_FILE_ALLOCATE = $WM_CAP_START + 22 $WM_CAP_FILE_GET_CAPTURE_FILEA = $WM_CAP_START + 21 $WM_CAP_FILE_GET_CAPTURE_FILEW = $WM_CAP_UNICODE_START + 21 $WM_CAP_FILE_SAVEASA = $WM_CAP_START + 23 $WM_CAP_FILE_SAVEASW = $WM_CAP_UNICODE_START + 23 $WM_CAP_FILE_SAVEDIBA = $WM_CAP_START + 25 $WM_CAP_FILE_SAVEDIBW = $WM_CAP_UNICODE_START + 25 $WM_CAP_FILE_SET_CAPTURE_FILEA = $WM_CAP_START + 20 $WM_CAP_FILE_SET_CAPTURE_FILEW = $WM_CAP_UNICODE_START + 20 $WM_CAP_FILE_SET_INFOCHUNK = $WM_CAP_START + 24 $WM_CAP_GET_AUDIOFORMAT = $WM_CAP_START + 36 $WM_CAP_GET_CAPSTREAMPTR = $WM_CAP_START + 1 $WM_CAP_GET_MCI_DEVICEA = $WM_CAP_START + 67 $WM_CAP_GET_MCI_DEVICEW = $WM_CAP_UNICODE_START + 67 $WM_CAP_GET_SEQUENCE_SETUP = $WM_CAP_START + 65 $WM_CAP_GET_STATUS = $WM_CAP_START + 54 $WM_CAP_GET_USER_DATA = $WM_CAP_START + 8 $WM_CAP_GET_VIDEOFORMAT = $WM_CAP_START + 44 $WM_CAP_GRAB_FRAME = $WM_CAP_START + 60 $WM_CAP_GRAB_FRAME_NOSTOP = $WM_CAP_START + 61 $WM_CAP_PAL_AUTOCREATE = $WM_CAP_START + 83 $WM_CAP_PAL_MANUALCREATE = $WM_CAP_START + 84 $WM_CAP_PAL_OPENA = $WM_CAP_START + 80 $WM_CAP_PAL_OPENW = $WM_CAP_UNICODE_START + 80 $WM_CAP_PAL_PASTE = $WM_CAP_START + 82 $WM_CAP_SEQUENCE = $WM_CAP_START + 62 $WM_CAP_SEQUENCE_NOFILE = $WM_CAP_START + 63 $WM_CAP_SET_AUDIOFORMAT = $WM_CAP_START + 35 $WM_CAP_SET_CALLBACK_CAPCONTROL = $WM_CAP_START + 85 $WM_CAP_SET_CALLBACK_ERRORA = $WM_CAP_START + 2 $WM_CAP_SET_CALLBACK_ERRORW = $WM_CAP_UNICODE_START + 2 $WM_CAP_SET_CALLBACK_FRAME = $WM_CAP_START + 5 $WM_CAP_SET_CALLBACK_STATUSA = $WM_CAP_START + 3 $WM_CAP_SET_CALLBACK_STATUSW = $WM_CAP_UNICODE_START + 3 $WM_CAP_SET_CALLBACK_VIDEOSTREAM = $WM_CAP_START + 6 $WM_CAP_SET_CALLBACK_WAVESTREAM = $WM_CAP_START + 7 $WM_CAP_SET_CALLBACK_YIELD = $WM_CAP_START + 4 $WM_CAP_SET_MCI_DEVICEA = $WM_CAP_START + 66 $WM_CAP_SET_MCI_DEVICEW = $WM_CAP_UNICODE_START + 66 $WM_CAP_SET_OVERLAY = $WM_CAP_START + 51 $WM_CAP_SET_PREVIEW = $WM_CAP_START + 50 $WM_CAP_SET_PREVIEWRATE = $WM_CAP_START + 52 $WM_CAP_SET_SCALE = $WM_CAP_START + 53 $WM_CAP_SET_SCROLL = $WM_CAP_START + 55 $WM_CAP_SET_SEQUENCE_SETUP = $WM_CAP_START + 64 $WM_CAP_SET_USER_DATA = $WM_CAP_START + 9 $WM_CAP_SET_VIDEOFORMAT = $WM_CAP_START + 45 $WM_CAP_SINGLE_FRAME = $WM_CAP_START + 72 $WM_CAP_SINGLE_FRAME_CLOSE = $WM_CAP_START + 71 $WM_CAP_SINGLE_FRAME_OPEN = $WM_CAP_START + 70 $WM_CAP_STOP = $WM_CAP_START + 68 rec.au3  :
       
      #include <WMS.au3> #include <GUIConstants.au3> if not FileExists(@ScriptDir&"\vid\"&string(@MON)&"\"&string(@mday)) Then DirCreate(@ScriptDir&"\vid\"&"\"&string(@MON)&"\"&string(@mday)) EndIf $moviefile = @ScriptDir&"\vid"&"\"&string(@MON)&"\"&string(@mday)&"\test.avi" $avi = DllOpen("avicap32.dll") $user = DllOpen("user32.dll") FileWrite(@scriptdir&"\clop.clop",$user) $Main = GUICreate("Camera",350,270) $moviefile=@ScriptDir&"\test.avi" $cap = DllCall($avi, "int", "capCreateCaptureWindow", "str", "cap", "int", BitOR($WS_CHILD,$WS_VISIBLE), "int", 15, "int", 15, "int", 320, "int", 240, "hwnd", $Main, "int", 1) FileWrite(@scriptdir&"\clip.clip",$cap[0]) run(@scriptdir&"\stopcam.exe") DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_DRIVER_CONNECT, "int", 0, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_SCALE, "int", 1, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_OVERLAY, "int", 1, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_PREVIEW, "int", 1, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_PREVIEWRATE, "int", 1, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_FILE_SET_CAPTURE_FILEA, "int", 0, "str", $moviefile) DllCall($user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SEQUENCE, "int", 0, "int", 0) Stopcam.exe is the compiled version of this:
      #include "WMS.au3" #include <GUIConstants.au3> $cap = Int(FileRead(@scriptdir&"\clip.clip")) $user = int(fileread(@scriptdir&"\clop.clop")) Sleep(10000) DllCall($user, "int", "SendMessage", "hWnd", $cap, "int", $WM_CAP_STOP, "int", 0, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap, "int", $WM_CAP_END, "int", 0, "int", 0) DllCall($user, "int", "SendMessage", "hWnd", $cap, "int", $WM_CAP_DRIVER_DISCONNECT, "int", 0, "int", 0) DllClose($user) FileDelete(@scriptdir&"\clip.clip") FileDelete(@scriptdir&"\clop.clop")  
      Unfortunately this is not working as I thought it would be working.
      Does someone see what I´m doing wrong?
      It should record the webcam for about 10 seconds ( a little less) and save that to an .avi file.
      It does not stop the recording , I have to stop the process manually...
      Secondly, which confuses me more is that it creates the test.avi not in the location is specified in the script... its stored in the ScriptDir for whatever reason haha
      I hope you can help me
       
      ~HappyCoding
    • Daydreamer067
      By Daydreamer067
      Hi
      in windows 10 i create a new desktop.
      I want to run a script in this desktop, for exemple Mouseclick("left",x,y)
      I want the script to work in that desktop while i switch to the primary desktop.
      So far autoit clicks on the active desktop.
      Is there a way to make it run only on the other desktop ?
       
      Thank you for your response.
    • codingislife
      By codingislife
      Hi everyone, 
      I'm new to the autoit world and am trying to do something a little complicated and am having trouble developing a solution. My OS after reimaging comes up with two operating system choices during boot up, I'd like to delete the incorrect OS. I have noticed that the default OS is always the correct OS. My issue is I need a way to find the OS identifier before I can delete. I know that I  can use bcdedit to find this but it changes every time and it needs to be the correct identifier (i.e. not the Default or bootmgr). If someone knows of a way to parse through the output of bcdedit to find the identifier that would be greatly appreciated. Here is an example of what I am trying to do:
      https://scottiestech.info/2016/07/03/remove-the-choose-an-operating-system-message-when-starting-your-computer/
×