Taskbar Notification Area Infotray oder Infoleiste --- aktualisieren

  • VB.NET

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von sonne75.

    Taskbar Notification Area Infotray oder Infoleiste --- aktualisieren

    Hallo Leute!
    Kurze Vorstellung: Ich bin ein Gelegenheitsprogrammierer, teilweise auch beruflich (verschiedene Sprachen), aber eigentlich mehr als Hobby. Und dann verwende ich "Microsoft Visual Studio 2012 Express", und dessen Sprache Visual Basic.

    Mein derzeitiges Problem ist, das ich in meinem Programm, zu gegebener Zeit ein anderes Programm welches ich in den Prozessen aufsuche, mit .Kill() beende. Es handelt sich um ein Programm, welches sich durch ein Icon im Infobereich zeigt, wenn es denn gestartet ist.

    Das Problem besteht nicht im beenden. Das funktioniert. Aber nach dem Kill Prozess bleibt dessen Icon im Infotray Bereich noch sichtbar. Obwohl es aber erfolgreich beendet (gekillt) wurde. Es handelt sich also nur um einen Anzeigefehler. Denn wenn ich mit der Maus über dieses Icon drüberfahre (ohne zu klicken oder sonstiges), verschwindet es (endlich).

    Nun suche ich schon seit Stunden im Internet nach einem Befehl, wie ich den Infobereich aktualisieren kann. Also refreshen oder neu zeichnen oder sowas wie ein redraw. Nix. Ich find einfach nix. Vielleicht kann mir hier wer weiter helfen?...

    Danke im Voraus.
    Viele Grüße,
    Hinti
    Willkommen im Forum. :thumbup:
    Du schmeißt ein Programm mit dem Vorschlaghammer raus und wunderst Dich, dass die Handschuhe an der reckstange kleben geblieben sind. :D
    Probier mal, mit API.SendMessage(WM_CLOSE)
    Gugst Du hier.
    und

    VB.NET-Quellcode

    1. Private Const WM_CLOSE As Integer = &H10
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo RodFromGermany,

    Ich glaube ich stufe mich jetzt doch runter zum Amateurprogrammierer, der nicht weiß was er tut ;(

    Danke für deine Antwort. Und sie leuchtet ein :D Aber... ich bin eben doch eher der Programmierer, der bisher eigentlich nur integrierte Funktionen verwendet hat. Nun klappt folgender Versuch nicht...

    Intialisierung, okay...

    Quellcode

    1. Declare Auto Function SendMessage Lib "user32.dll" (
    2. ByVal hWnd As IntPtr,
    3. ByVal msg As Integer,
    4. ByVal wParam As IntPtr,
    5. ByVal lParam As IntPtr) As IntPtr
    6. Private Const WM_CLOSE As Integer = &H10

    Aufruf tut aber nix (p.Kill ersetzt durch SendMessage) :!::

    Quellcode

    1. Dim p As Process
    2. For Each p In Diagnostics.Process.GetProcesses()
    3. If p.ProcessName.ToLower = "zubeendendesprogramm" Then
    4. 'p.Kill()
    5. SendMessage(p.Handle, WM_CLOSE, 0, 0)
    6. Exit For
    7. End If
    8. Next


    bekomm ich noch einen Hinweis :?: :love:
    Probier mal.

    VB.NET-Quellcode

    1. p.MainWindowHandle


    Falls das auch nicht geht, dann setz mal einen Haltepunkt und schau, ob die Codezeile überhaupt erreicht wird. Du musst auch nicht alle Prozesse durchgehen. Es gibt auch das da.

    VB.NET-Quellcode

    1. Dim p() As Process = Process.GetProcessesByName("processname")
    2. If p.Count > 0 Then
    3. SendMessage(p(0).MainWindowHandle, WM_CLOSE, 0, 0)
    4. End If
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    Hinti schrieb:

    bekomm ich noch einen Hinweis :?:
    Zunächst probieren wir das ganze mal aus:
    SendMessage

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    4. Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    5. End Function
    6. Private Const WM_CLOSE As Integer = &H10
    7. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    8. Dim p() As Process = Process.GetProcessesByName("NotePad")
    9. If p.Count > 0 Then
    10. SendMessage(p(0).MainWindowHandle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero)
    11. End If
    12. End Sub
    13. End Class
    Füge das bei Dir ein (ich hab die .NET-Deklaration genommen), starte das Notepad und probier das mal aus und dann änderst Du den Prozess-Namen.
    Und verfolge das ganze mal im Taskmanager. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Zunächst habe ich die Schleife ersetzt durch den Direktaufruf. Vielen Dank für den Tipp :)

    Folgende Zeile wird also aufgerufen (mit Debug überprüft):

    Quellcode

    1. SendMessage(p(0).MainWindowHandle, WM_CLOSE, 0, 0)

    Leider tut sich noch immer nix. Programm bleibt davon unberührt :evil:

    p(0).kill tut an der Stelle was ich will. Aber eben mit dem Vorschlaghammer!
    Noch Ideen... ?(

    Hinti schrieb:

    Leider tut sich noch immer nix.
    Beschreib mal den Prozess, den Du killen willst.
    Hat dieser überhaupt ein MainWindowHandle?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also folgendes.

    Mit Notepad funktioniert es. Mein Programm (welches ich schliessen möchte) hat allerdings keinen MainWindowHandle (= 0). Dafür aber einen Handle (p(0).Handle). Damit funktionierts aber nicht. Eben nur mit .Kill().

    Es handelt sich um ein exe-Datei, welches als Monitor einer bestimmten Software fungiert. Also eine Überwachungssoftware für diverse Dienste. Es gibt kein Taskbaricon. Nur das InfotrayIcon.

    :?: :?:
    SendMessage sendet eben eine Nachricht an ein Window. Spätestens da hättest Du uns mit dieser kleinen Information versorgen sollen, damit wir nicht umsonst suchen.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Kannst es Dir ja fürs nächste mal merken. Immer gleich alle Informationen raushauen, dann kann man Dir am besten helfen....
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Ja klar merke ich mir das. Ist mir sehr peinlich. Aber ich habe es nicht mit Absicht gemacht. Diesem Unterschied habe ich leider keine Bedeutung beigemessen. Vorallem war er mir gar nicht bewußt. Wie gesagt. Bisher verwende ich eigentlich nur Standardsourcecode ("Hello World" & Co). Keine externen Programmaufrufe, (SendMessage) usw.

    Können wir jetzt nochmal von vorne anfangen?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Hinti“ ()

    Ich glaube nicht, das es eine Lösung für das Problem gibt. Wenn Du kein MainWindowHandle hast, dem Du sagen kannst, es soll sich beenden und somit (in vielen Fällen) auch das Programm, dann sehe ich hier keine Möglichkeit, das Icon loszuwerden. Rufst Du Process.Kill() auf, wird der Prozess sofort abgebrochen, er hat gar keine Möglichkeit mehr, seine Ressourcen zu bereinigen/freizugeben. Ich glaube, es war bisher in allen Windows-Versionen so, dass durch einen Taskmananger-Kill ein evtl. vorhandenes NotifyIcon bestehen bleibt. Erst, wenn Du mit der Maus über dieses Icon "fährst", wird versucht, eine Nachricht an das Programm abzusetzen und erst hier bekommt Windows mit, dass es diesen Prozess gar nicht mehr gibt. Kann man wohl als "Windows-Bug" einstufen.

    Ohne MainWindowsHandle keine Chance in meinen Augen. Ich lass mich aber gerne eines Besseren belehren.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    SpaceyX schrieb:

    Erst, wenn Du mit der Maus über dieses Icon "fährst", wird versucht, eine Nachricht an das Programm abzusetzen und erst hier bekommt Windows mit, dass es diesen Prozess gar nicht mehr gibt.


    Ich sage gleich, ich habe wirklich Null Ahnung davon. Aber könnte man diesen Versuch eine Nachricht an das Programm zu schicken, simulieren? Das Gleiche tun, was Windows erst tut, wenn die Maus drüber fährt? Oder wenigstens die Maus"berührung" simulieren, damit diese Nachricht automatisch ausgelöst wird?

    Hinti schrieb:

    Ist mir sehr peinlich.
    Das muss Dir absolut nicht peinlich sein, zumal Du absolut nicht lernresistent bist. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @sonne75

    Seit dieser Thread gepostet wurde, sitze ich da und google mir die Finger wund. Viele Leute fragen nach diesem Problem, aber eine Lösung konnte ich wirklich nirgends finden. Es scheint wirklich ein "altbackenes" Problem zu sein und wenn bis heute keine Lösung dafür gefunden wurde, dann muss man das eben akzeptieren.

    Sicher mag es Wege geben, um es letztendlich doch zu schaffen. Doch rechtfertigt das nicht den Aufwand.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    @Hinti: Google mal vlt. nach "API vb.net mouse" denn im kernel32 muss es ja die funktion zum verschieben des cursors geben welche über einem best. pixel eben ein event aktiviert und somit das icon löscht/verschwinden lässt. [/Geekmode] :D
    Ich werfe nochmal ne primitive Frage hinten nach. Eigentlich ist ja schon gesagt das es keine Lösung dafür gibt. Aber gibt es denn auch keine Möglichkeit einer Schleife aller NotifyIcons? ala Schleife wie man auch alle Prozesse scannen kann?

    sowie:
    For Each b In Diagnostics.Windows.Infotray.GetIcons()

    oder etwas wie?...
    System.Infotray.Refresh()

    (aber im Grunde genommen habe ich mich eh schon damit abgefunden :|)