Herausfinden, Welches Programm gerade im Vordergrund läuft

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von DTF.

    Herausfinden, Welches Programm gerade im Vordergrund läuft

    Hallo an euch Profis,

    ich möchte ein keines Macropad erstellen das je nach dem im Vordergrund laufenden Programm bestimmte Funktionen auf einen Button legt.
    Dafür muss ich natürlich wissen, welches Programm nun gerade aktiv ist. Alleine bekomme ich das nicht hin und die Websuche war auch nicht erfolgreich.
    Wie kann ich das am besten angehen?
    Man(n) kann auch ohne Hunde leben, aber es lohnt nicht (Heinz Rühmann)
    @Skino Dafür gibt es die Funktion

    VB.NET-Quellcode

    1. <DllImport("User32.dll")>
    2. Friend Shared Function GetForegroundWindow() As IntPtr
    3. End Function
    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!
    naja, bisserl mehr muss schon noch kommen:

    VB.NET-Quellcode

    1. <DllImport("User32.dll")>
    2. Friend Shared Function GetForegroundWindow() As IntPtr
    3. End Function
    4. <DllImport("User32.dll")>
    5. Friend Shared Function GetWindowThreadProcessId(hWnd As IntPtr, ByRef lpdwProcessId As Integer) As UInt32
    6. End Function
    7. Private Shared Function GetForegroundProcess() As Process
    8. Dim pid As Integer
    9. Dim hwnd = GetForegroundWindow()
    10. Dim success = GetWindowThreadProcessId(hwnd, pid)
    11. Return Process.GetProcessById(pid)
    12. End Function
    Danke euch beiden. GetForegroundProcess hatte ich auch auf der Liste aber damit habe ich nichts hinbekommen.
    Jetzt komme ich weiter.
    Man(n) kann auch ohne Hunde leben, aber es lohnt nicht (Heinz Rühmann)
    @Skino Kannst Du mal Dein Problem etwas genauer beschreiben?
    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!
    Es funktioniert so wie ich es mir vorgestellt hatte. Kein Wunder, Copy and Paste
    Frage: Ich habe den Aufruf der Funktion in einem Timerevent. Ist das der richtige Weg?

    Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. Label1.Text = GetForegroundProcess().ToString
    3. End Sub

    Man(n) kann auch ohne Hunde leben, aber es lohnt nicht (Heinz Rühmann)

    Skino schrieb:

    Ist das der richtige Weg?


    Ein Hook wäre meine Wahl.

    learn.microsoft.com/en-us/wind…f-winuser-setwineventhook

    Für die Parameter eventMin und eventMax EVENT_SYSTEM_FOREGROUND nehmen.
    learn.microsoft.com/en-us/wind…2/winauto/event-constants

    Aber dafür musst du dich mit Pinvoke auskennen, die Seite pinvoke.net ist ja leider scheinbar tot, aber evtl. kannste ja sonstwo was finden, falls du das nicht selbst umsetzen kannst.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Skino schrieb:

    Ist das der richtige Weg?
    Was soll denn angezeigt werden? Hier siehst Du nur das Handle, das ist ein IntPtr.
    Wenn Du den Titel des Fensters haben willst, musst Du den Snippet vom EDR nehmen und aus der Prozess-Instanz den Process.MainWindowTitle auslesen:
    learn.microsoft.com/de-de/dotn…nwindowtitle?view=net-7.0
    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!
    Richtig. Es geht mir um den Titel des Fensters bzw. Name des Programmes. Einfach eine eindeutige Identifizierung welches Programm gerade im Vordergrund läuft.

    Edit: ".MainWindowTitle" war eine genialer Tipp Vielen Dank dafür
    Man(n) kann auch ohne Hunde leben, aber es lohnt nicht (Heinz Rühmann)
    @Skino

    Hatte eine tolle Idee wofür ich sowas einsetzen könnte, hab ein wenig Code prepariert und den Code vom EDR einfliessen lassen. Kannste dir übersetzen mit einem Converter, dann kommste ohne Timer aus.

    C#-Quellcode

    1. using System.ComponentModel;
    2. using System.Diagnostics;
    3. using System.Runtime.InteropServices;
    4. namespace ForegroundHook
    5. {
    6. public partial class Form1 : Form
    7. {
    8. public Form1()
    9. {
    10. InitializeComponent();
    11. }
    12. [DllImport("user32.dll")]
    13. private static extern nint GetForegroundWindow();
    14. [DllImport("user32.dll", SetLastError = true)]
    15. private static extern nint SetWinEventHook(int eventMin, int eventMax, nint hmodWinEventProc, EventDelegate pfnWinEventProc, int idProcess, int idThread, int dwflags);
    16. [DllImport("user32.dll", SetLastError = true)]
    17. private static extern int UnhookWinEvent(nint hWinEventHook);
    18. [DllImport("User32.dll")]
    19. internal static extern uint GetWindowThreadProcessId(nint hWnd, ref int lpdwProcessId);
    20. private nint HookHandle;
    21. private delegate void EventDelegate(nint hWinEventHook, uint _event, nint hwnd, int idObject, int idChild, uint idEventThread, uint dwmsEventTime);
    22. private const int WINEVENT_OUTOFCONTEXT = 0;
    23. private const int WINEVENT_SKIPOWNPROCESS = 2;
    24. private const int EVENT_SYSTEM_FOREGROUND = 3;
    25. private void HookCallback(nint hWinEventHook, uint _event, nint hwnd, int idObject, int idChild, uint idEventThread, uint dwmsEventTime)
    26. {
    27. Debug.WriteLine(GetForegroundProcess(hwnd).MainWindowTitle);
    28. }
    29. private Process GetForegroundProcess(nint handle = 0)
    30. {
    31. int pid = 0;
    32. if(handle == 0)
    33. {
    34. handle = GetForegroundWindow();
    35. }
    36. uint success = GetWindowThreadProcessId(handle, ref pid);
    37. return Process.GetProcessById(pid);
    38. }
    39. private void Form1_Load(object sender, EventArgs e)
    40. {
    41. Debug.WriteLine(GetForegroundProcess(0).MainWindowTitle);
    42. HookHandle = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, 0, HookCallback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
    43. if (HookHandle == 0) throw new Win32Exception(Marshal.GetLastWin32Error());
    44. }
    45. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    46. {
    47. if(HookHandle != 0)
    48. {
    49. UnhookWinEvent(HookHandle);
    50. }
    51. }
    52. }
    53. }

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Mit so Window-Hooks habich früher schlechte ERfahrungen gemacht.
    Wenn ich solche Anwendungen entwickelt habe, und es kam zu Exceptions an ganz anderer Stelle, sodass der Testlauf abgebrochen werden musste - da flog mir die ganze IDE raus,weil das Hooking nicht ordentlich zurückgenommen werden konnte.
    Also Fehler verursachten verheerende Folge-Fehler durch unaufgeräumte Hooks.
    Aber vlt. ist das inzwischen ja besser geworden, oder es gilt nur für bestimmte Hooks, oder es gibt inzwischen Lösungen dafür.

    Ich würd das aber erstmal prüfen, bevor man sich sone Laus in den Pelz setzt.

    Etwa: was passiert, wenn das gehookte Form1 nicht das MainForm ist, und abstürzt, oder aus sonst einem Grund schliesst, ohne zu unHooken?
    Und MainForm soll aber weiterlaufen?

    Oder statt nur MainWindowTitle zu debuggen mach mal etwas aufwändigeres damit.
    Oder zeigs einfach mal in einer Messagebox an.
    Messagebox ist ja modal und blockiert dadurch dann den Hook-Callback-Thread.

    Ausserdem kommt die Messagebox in den Vordergrund, da wäre also eine neue WinApi-Message fällig, aber der Thread ist ja blockiert...

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Bisher habe ich keine schlechten Erfahrungen machen dürfen mit Hooks, ausser mit Scherzprogrammen. Kürzlich durch meinen Neffen(dem bring ich Programmieren bei), der hat mir glatt ein Programm in den Autostart gepackt mit Mousehook der die Bewegungen umdrehte. Hab ihm dann aber gezeigt warum man sowas nicht zu tun hat(Auch mögliche rechtliche Konsequenzen erklärt). Der konnte halt nicht mehr spielen auf seinem Laptop, man war der sauer, weil das Internet immer wenn er Steam startete nicht mehr ging(Netzwerkverbindungen abgeschaltet). Ich hoffe das war im eine Lehre, hab ihn auch erstmal fummeln lassen, bevor ich das wieder entfernte. Hab das aber auch ganz fies versteckt(in einem anderen Prozess)

    BTT:
    Also wenn ein Hook nicht wieder entfernt wird sollte das eigendlich kein Problem sein, weil genutzt werden Funktionspointer, also die Speicheradressen von Funktionen, welche ja ungültig werden sollte das Fenster nicht da sein oder das Programm sich ganz verabschieden.

    Auch MS sagt das man Hooks meiden sollte, weil das die Systemperformce beeinträchtigen kann, auch zu Konflikten führen kann.

    OK ein Hook ist evtl. ein wenig Overkill für diesen Zweck, aber es hängt auch davon ab, ob wirklich jeder Wechsel registrirert werden soll, was mit einem Timer nicht klappen würde.

    MessageBoxen in Callback-Funktionen sind nie eine gute Idee, in diesem Fall sogar eine sehr schlechte, weil durch dessen aufpoppen und wegklicken eine Schleife entsteht, aber in diesem Kontext sollte die Ursache dem Dev klar sein.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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