Bei den meisten Windows Benutzern befindet sich unten rechts auf dem Bildschirm die Uhr - und links davon der so genannte Infobereich.
Wenn sich dort ein neues Programm festsetzt wird dieses zunächst für maximal 45 Sekunden angezeigt - und danach ausgeblendet.
Es ist dann über den kleinen Pfeil nach oben erreichbar.
Für ein Programm (Windows Host vom Desktop aus in Zabbix in den Wartungsmodus setzen und den Status mit Countdown anzeigen) wollte ich nun das direkt nach der Installation das Icon im Infobereich sichtbar ist.
Gefunden hatte ich diese Lösung dafür: https://tmintner.wordpress.com/2011/07/08/win…ry-rabbit-hole/
AspirinJunkie hat mir den Weg gezeigt wie ich die Binärdaten richtig auslese: Binärdaten aus Registry manipulieren - PowerShell oder Visual Basic Skript umsetzen
UEZ hat mich mit dem vom File to Base64 String Generator erzeugten Code auf die Idee gebracht wie ich die Bytes manipulieren kann (nämlich DllStructCreate, DllStructSetData und DllStructGetData
Und hier nun der Beispielcode mit dem man das AutoIt-Programm immer als Symbol angezeigt bekommt während ein Programm läuft.
Wenn das Programm nur gefunden schreibt und nichts macht müsst Ihr mal ein anderes wählen oder das Symbol händisch ausblenden.
Nicht erschrecken: Falls der Wert angepasst wird, wird auch die Explorer.exe neu gestartet, sonst ignoriert und überschreibt Windows den Wert wieder.
Hier der Code:
#include <WinAPISys.au3>
#include <WinAPI.au3>
#include <Array.au3>
; Demoprogramm um Tray Icons dauerhaft sichtbar zu machen.
; Neue Icons im Info-Bereich werden spätestens nach 45 Sekunden ausgeblendet - mit diesem Kniff ist es immer sichtbar ohne das der benutzer dies einstellen muss
; Siehe https://tmintner.wordpress.com/2011/07/08/windows-7-notification-area-automation-falling-back-down-the-binary-registry-rabbit-hole/
; Am besten in SciTE ausführen, im Consolenfenster werden dann die Werte dargestellt
Global $s_Program = "AutoIt3.exe" ; Das Icon für dieses programm immer sichtbar machen, ggf. mit Pfad (ganz oder in Teilen)
Global $TrayVis_ShowOnlyNotification = 0 ; only show notifications
Global $TrayVis_HideBoth = 1 ; hide icon and notifications
Global $TrayVis_ShowBoth = 2 ; show icon and notifications
Global $b_ExPath
Global $b_IconStreamsRAW = RegRead("HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify", "IconStreams")
Global $d_BlockSize = 1640
Global $i_BytePos = 21 ; in den ersten 20 Bytes steht der Header - überspringen
While $i_BytePos < BinaryLen($b_IconStreamsRAW)
$b_ExPath = BinaryMid($b_IconStreamsRAW, $i_BytePos, 528)
;~ $s_ExePath = StringRegExpReplace(_Rot13(StringStripWS(BinaryToString($b_ExPath, 2), 8)), "((?<=exe).*)$", "")
$s_ExePath = StringRegExpReplace(_Rot13(StringStripWS(BinaryToString($b_ExPath, 2), 8)), "(((?<=exe).*)$|\x0|\x1)", "")
$b_NotificationVisibilitySetting = BinaryMid($b_IconStreamsRAW, $i_BytePos + 528, 4)
ConsoleWrite($s_ExePath & " --> " & $b_NotificationVisibilitySetting & " ")
Switch $b_NotificationVisibilitySetting
Case "0x00000000"
ConsoleWrite("(only show notifications)" & @CRLF)
Case "0x01000000"
ConsoleWrite("(hide icon and notifications)" & @CRLF)
Case "0x02000000"
ConsoleWrite("(show icon and notifications)" & @CRLF)
EndSwitch
; Prüfen ob unser Wunschprogramm dabei ist:
If StringInStr($s_ExePath, $s_Program) > 0 Then
ConsoleWrite(@CRLF & "Gefunden: " & $s_Program & " ==> " & $s_ExePath & @CRLF & @CRLF)
If Int(StringLeft($b_NotificationVisibilitySetting,4)) <> $TrayVis_ShowBoth Then
; Ist nicht Sichtbar!
; Für eine Leiste oben welche die einzelnen Blöcke markiert
; 1234567890123456789012345678901234567890
ConsoleWrite(" ") ;Die ersten 20 Bytes überspringen + das 0x am Anfang
For $i = 1 To (BinaryLen($b_IconStreamsRAW) - $d_BlockSize) Step $d_BlockSize
For $j = 1 To ($d_BlockSize - 1) Step 1
If $j = 528 Then
ConsoleWrite("##")
Elseif $j = 532 Then
ConsoleWrite("##")
Else
Consolewrite("..")
EndIf
Next
ConsoleWrite("||")
Next
ConsoleWrite(@CRLF)
; Nun einmal die Roh-Daten vor der Änderung
ConsoleWrite($b_IconStreamsRAW & @CRLF)
; Wir müssen nun das einzelne Byte ändern
Local Const $tagSTRUCT1 = "struct;byte var1[" & ($i_BytePos + 527) & "];byte var2[4];byte var3[" & (BinaryLen($b_IconStreamsRAW) - ($i_BytePos + 531)) & "];endstruct"
Local $tSource = DllStructCreate($tagSTRUCT1)
DllStructSetData($tSource, "var1", BinaryMid($b_IconStreamsRAW, 1, $i_BytePos + 528)) ; Anfang
DllStructSetData($tSource, "var2", $TrayVis_ShowBoth) ; unser geändertes Byte
DllStructSetData($tSource, "var3", BinaryMid($b_IconStreamsRAW, $i_BytePos + 532)) ; und den Rest wieder dranhängen
Local $b_NewIconStreamsRAW = Binary(DllStructGetData($tSource, 1) & DllStructGetData($tSource, 2) & DllStructGetData($tSource, 3)) ; Wieder einen Wert daraus bauen
ConsoleWrite($b_NewIconStreamsRAW & @CRLF) ; Unter den ausgelesenden Wert schreiben zum Vergleich
For $i = 1 To ($i_BytePos + 528) Step 1 ; einen Anzeiger bauen an welcher Stelle wir suchen müssen
ConsoleWrite("==")
Next
ConsoleWrite("=|" & @CRLF)
ConsoleWrite(Binary(DllStructGetData($tSource, 1)) & " -> var1" & @CRLF) ; die ersten 528 Bytes
ConsoleWrite(Binary(DllStructGetData($tSource, 1) & DllStructGetData($tSource, 2)) & " -> var1 + var2" & @CRLF) ; die ersten 528 Bytes + die 4 Bytes für die Anzeige
; Problem: Wir haben hinter dem Rücken der Explorer.exe den Wert geändert.
; Jedesmal wenn diese beendet wird schreibt diese auch noch mal den Wert.
; Also müssen wir 1. Die Explorer.exe beenden
; 2. Den neuen Registry-Wert schreiben
; 3. Die Explorer.exe wieder starten
; Hier gefunden: https://www.autoitscript.com/forum/topic/189906-restart-explorerexe/?do=findComment&comment=1363358
;Save icon positions (probably not needed since we are doing a graceful exit ..)
DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x8000000, "uint", BitOR(0x0, 0x1000), "ptr", 0, "ptr", 0)
;Close the explorer shell gracefully
$h_SysTray_Handle = _WinAPI_FindWindow('Shell_TrayWnd', '') ; Zeiger holen
_SendMessage($h_SysTray_Handle, 0x5B4, 0, 0) ; "Bitte beenden" senden
While WinExists($h_SysTray_Handle) ; Warten bis beendet ist ...
Sleep(500)
WEnd
Sleep(500) ; Sicherheitshalber kurze Pause und dann den Schlüssel schreiben
RegWrite("HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify", "IconStreams", "REG_BINARY", $b_NewIconStreamsRAW)
Sleep(500)
_start_explorer() ; Explorer.exe wieder starten ...
While Not _WinAPI_GetShellWindow() ; Warten das diese gestartet ist ...
Sleep(500)
WEnd
;~ EnvUpdate() ; Würde die Umgebungsvariablen aktualisieren
;~ ExitLoop; Wir hatten unseren Treffer, raus aus der Schleife
Else
;~ ExitLoop
EndIf
EndIf
$i_BytePos += $d_BlockSize
WEnd
Exit
; Funktionen ###########################################################################################################################
Func _start_explorer()
; Startet die Explorer.exe, wartet nicht, stößt es nur an
$strComputer = "localhost"
$objWMI = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
Local $objexplorer = $objWMI.Get("win32_process")
$objexplorer.create("explorer.exe")
EndFunc ;==>_start_explorer
Func _Rot13($s_Input)
; by AspirinJunkie
Local $s_Ret = ""
For $a_C In StringRegExp($s_Input, "(?>([N-Zn-z])|([A-Za-z])|(.))", 4)
$s_Ret &= ChrW(AscW($a_C[0]) + (UBound($a_C) = 2 ? -13 : (UBound($a_C) = 3 ? 13 : 0)))
Next
Return $s_Ret
EndFunc ;==>_Rot13
; https://www.autoitscript.com/forum/topic/103871-_systray-udf/
Alles anzeigen
Verbesserungsvorschläge höre ich gern!
BLinz