Home > Enterprise >  C#: Get informed when any new process is started / any new window is opened
C#: Get informed when any new process is started / any new window is opened

Time:11-17

I need to check when a new process with a new visible main window handle is started (as the mouse hook of my app is lost on some applications and is restored only on a short internal restart).

I have tried to use EnumWindows and EnumDesktopWindows but those give me many many windows and child windows I do not need. I only need the visible main window handles. Therefore (and to find out if they are belonging to a new process) I decided to directly check the processes within an own update-check-thread. But this approach (as well as to permanently check EnumWindows) is extremely cpu consuming (1-3 % at Ryzen 5600X) and in my opinion, completely overblown.

Therefore I'd like to know if there is any other, slick approach to find out whenever any new process is started or window is opened to only execute the check when it is necessary.

CodePudding user response:

Polling is never a good solution.

If you are already hooking, why not use WH_SHELL, WH_CBT or SetWinEventHook()?

CodePudding user response:

I solved it by using/extracting the ApplicationWatcher from this Package with minor adjustments to run it within .NET v4.5.2 and to get rid of all unnecessary things.

The application event hook only works for apps/windows which are started after the event hook has been launched which is sufficient for my purposes. If one needs all existing windows as well, you once need to add all existing windows to the activeWindows property of the ApplicationWatcher class.

Furthermore, the WindowsActivated event seems to be bugged. Herefore, you need to adjust the following things:

Within the ApplicationWatcher class

private void WindowActivated(WindowData wnd) {
  if (_ActiveWindows.ContainsKey(wnd.HWnd)) {
    if (!_LastEventWasLaunched) { // < if condition adjusted
      ApplicationStatus(_ActiveWindows[wnd.HWnd], ApplicationEvents.Activated);
    }
  }

  _LastEventWasLaunched = false;
}

and within the ShellHook class

protected override void WndProc(ref Message m) {
  if (m.Msg == _wmShellHook) {
    switch ((User32.ShellEvents)m.WParam) {
      ...

      case User32.ShellEvents.HSHELL_RUDEAPPACTIVATED: // < line added
      case User32.ShellEvents.HSHELL_WINDOWACTIVATED:
        if (WindowActivated != null) {
          WindowActivated.Invoke(this, m.LParam);
        }
        break;
    }
  }

  base.WndProc(ref m);
}

Works like a charme and my CPU usage went down to 0 %.

  • Related