Event für WindowCreate von anderem Prozess

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Gelöschter Benutzer.

    Event für WindowCreate von anderem Prozess

    Ich komm einfach nicht weiter:

    Ich hab eine Anwendung geschrieben, die immer sporadisch durch ein Fenster einer anderen Anwendung blockiert wird.
    Nun kann ich das Fenster Handle über FindWindow ermitteln, dort dementsprechenden Button drücken und dann verschwindet das Fenster.
    Wie schaffe ich es aber nun in meinem Programm drauf zu reagieren, wenn genau dieses Fenster erscheint? Genauer gesagt, wie schaffe ich es überhaupt zu reagieren wenn ein neues Fenster in Windows erzeugt wird, welches nicht zu meiner Anwendung gehört?
    Ich kann den Prozess ermitteln, der das Fenster erzeugt, aber weiter komme ich nicht.
    Irgendwo habe ich was von WinEvents gelesen, aber kein Beispiel gefunden, welches mir weiter hilft.
    Hi,

    du kannst einen Shell-Hook machen. Wenn da dann die Nachricht HSHELL_WINDOWCREATED(nCode) durchkommt, wurde ein Top-Level-Fenster erstellt. Bei dieser Nachricht enthält wParam dann auch das Handle dieses Fensters.
    msdn.microsoft.com/en-us/library/ms644991(VS.85).aspx
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

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

    Also ich hab den Code getestet und er funktioniert, war nur eine implizite Convertierung drin was ich korrigierte, dann war das auch schon Option Strict. Ich habe das mal .net-Konform gemacht. Nun kannst du auch detailierter schauen wenn wo ein Fehler auftritt. Auch die Rückgabetypen sind nun so wie inner MSDN beschrieben.

    Wenn das so bei dir auch nicht laufen sollte, musst du wohl eine Native DLL machen und mit SetWindowsHookEx arbeiten. Die NativeDll musst du dann laden und mit GetModuleHandle einen Pointer hohlen, welcher als Argument in SetWindowsHookEx für hInstance genutzt wird. So einfach wie mit Keyboard- oder Mouse-Hooks ist das leider nicht.

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Private Shell As UInteger
    4. Private Enum ShellEvents
    5. HSHELL_WINDOWCREATED = 1
    6. HSHELL_WINDOWDESTROYED = 2
    7. HSHELL_ACTIVATESHELLWINDOW = 3
    8. HSHELL_WINDOWACTIVATED = 4
    9. HSHELL_GETMINRECT = 5
    10. HSHELL_REDRAW = 6
    11. HSHELL_TASKMAN = 7
    12. HSHELL_LANGUAGE = 8
    13. HSHELL_ACCESSIBILITYSTATE = 11
    14. End Enum
    15. <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    16. Private Shared Function RegisterWindowMessage(ByVal lpString As String) As UInteger
    17. End Function
    18. <DllImport("user32.dll", SetLastError:=True)>
    19. Private Shared Function DeregisterShellHookWindow(ByVal hWnd As IntPtr) As Boolean
    20. End Function
    21. <DllImport("user32.dll", SetLastError:=True)>
    22. Private Shared Function RegisterShellHookWindow(ByVal hWnd As IntPtr) As Boolean
    23. End Function
    24. <DllImport("kernel32.dll")>
    25. Private Shared Function GetLastError() As Integer
    26. End Function
    27. Private Sub Log(ByVal what As String, ByVal errorCode As Integer)
    28. Debug.WriteLine(what & " ErrorCode " & errorCode)
    29. End Sub
    30. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    31. Shell = RegisterWindowMessage("SHELLHOOK")
    32. If Shell = 0 Then
    33. Log("RegisterWindowMessage returned 0! Error Code: ", GetLastError())
    34. Else
    35. If Not RegisterShellHookWindow(Handle) Then
    36. Log("RegisterShellHookWindow returned false! Error Code: ", GetLastError())
    37. End If
    38. End If
    39. End Sub
    40. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    41. If Not DeregisterShellHookWindow(Handle) Then
    42. Log("DeregisterShellHookWindow returned false! Error Code: ", GetLastError())
    43. End If
    44. End Sub
    45. Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    46. If m.Msg = Shell Then
    47. Select Case m.WParam.ToInt32
    48. Case ShellEvents.HSHELL_WINDOWCREATED
    49. Log("window created: " & m.LParam.ToInt32, 0)
    50. End Select
    51. End If
    52. MyBase.WndProc(m)
    53. End Sub
    54. End Class

    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „NoIde“ ()

    Klappt leider nicht. Es werden keine Events der anderen Software erkannt. Wenn ich mein eigenes Fenster Handle (wie im Beispiel) übergebe funktioniert es.
    Ich denke ich muss doch mit WinEvents arbeiten. Da hab ich aber bisher kein einziges vb.net beispiel gefunden.

    Ich müsste nur irgendwie in meiner Software einen Handler registrieren, der reagiert, wenn ein neues Fenster im Windows erzeugt wird.

    Gelöschter Benutzer schrieb:

    Ich müsste nur irgendwie in meiner Software einen Handler registrieren, der reagiert, wenn ein neues Fenster im Windows erzeugt wird.


    Genau das macht der Code. Der Effekt ist, das diese Nachrichten auch durch dein WndProc kommen.

    Zeige mal einen Screenshot von deinem Direktfenster, also wo die Ausgabe stattfindet, nachdem dein Programm gestartet ist. So das ich mal sehen kann, was wo für Errorcodes kommen.



    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    Kann ich dir schon zeigen, aber was als nächstes noch dazu kommt ist: Ich hänge mich als Addin an eine Software dran und bin somit keine Windows.Forms Anwendung. Ich denke ein Überschreiben der Funktion WndProc wird bei mir nicht funktionieren.

    **Edit**
    Das Direktfenster bleibt leer.
    Ja denn mach das mal, immerhin sind diese ErrorCodes dazu da, um festzustellen, was schief ging :!:

    docs.microsoft.com/en-us/windo…/debug/system-error-codes


    Edit: @gegy

    Gelöschter Benutzer schrieb:

    Wenn ich mein eigenes Fenster Handle (wie im Beispiel) übergebe funktioniert es.


    Also funktioniert es doch. Das Handle ist dafür da, damit das System auch weiss, an welches WndProc die Nachrichten sollen, also dein Fenster. Nutze mal dein Handle, lass die App laufen und starte mal den Windows Taschenrechner, wetten die message kommt an? Nutzt du ein anderes FensterHandle, wird die Nachricht an dessen WndProc geschickt.
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „NoIde“ ()

    Ah ok, ich hab da wohl was falsch verstanden gehabt: Dachte ich muss das an RegisterShellHookWindow das Fensterhandle der anderen Applikation übergeben.
    Ok, ich bekomme nun ausgaben, wenn ich z.b. Notepad starte. Auch wenn ich meine andere Applikation starte wird dieses ausgegeben. Aber der Dialog den ich schließen möchte, scheint kein standard Fenster zu sein. Zumindest bekomme ich keine Ausgabe, wenn der Dialog erscheint. Es geht hier um einen Speicherdialog.

    Und ich möchte es nochmal erwähnen, ich kann die Funktion WndProc in meiner Applikation nicht überschreiben, weils keine Windows Form Anwendung ist.
    Also jedes Fenster hat wohl ein WndProc, egal ob Winforms oder nicht(TopLevelWindows auf jeden Fall!). Also das keine Message beim deinem Speicherdialog kommt, liegt daran das es kein Top-Level-Window ist. Da wirst du wohl pollen müssen, also Turnusmässig via FindWindow oder so testen ob das Fenster da ist.

    Meist ist kurz bevor so ein Savefiledialog erscheint, ein klick auf einen Button notwendig(userinput generell), dann sollte HSHELL_APPCOMMAND durchs WndProc kommen, wenn du feststellen kannst ob dieser entsprechende Button geklickt wurde, musst du nicht durchgehend pollen, nur dann wenn der Button gedrückt wurde.
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „NoIde“ ()

    ​wenn du feststellen kannst ob dieser entsprechende Button geklickt wurde


    Nein, das geht nicht.

    Gut, ich will dir mal genauer erklären, was ich mache: Ich schreibe ein Addin für eine 3D CAD Software. Es gibt eine Addinschnittstelle, sodass es für den Anwender so wirkt, als wär mein Tool Teil der CAD Software. Nun führ meine Software einige Schritte automatisiert (ausgelöst über die API der CAD Software) aus. Ab und zu kommt es aber vor, dass ein Speicherdialog von der CAD Software eingeblendet wird und die Ausführung meines Tools erst fortgeführt wird, wenn dieser Dialog vom Anwender quittiert wird. Der Anwender möchte das aber nicht. Darum brauche ich eine Möglichkeit diesen Automatisch zu bestätigen. Ich kann das Fenster finden, aber ich weiß nie wann es kommt.