Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with SetForegroundWindow in .NET

I'm using SetForegroundWindow API in .NET using PInvoke.

When I use the API while debugging in Visual Studio its works perfectly. But it doesn't work always when the application is running normally.

I put some logs just before a call to SetForegroundWindow and its confirmed that the API is getting called but doesn't take effect at times. I have also seen a couple of posts regarding this issue but I want to know why is it failing.

The links of the post are a follows:

  • Win32 SetForegroundWindow unreliable
  • SetForegroundWindow only working while visual studio is open
like image 984
Aster Veigas Avatar asked Dec 07 '13 18:12

Aster Veigas


2 Answers

In fact this is a pure Win32 issue rather than a .net specific issue. The .net framework stands on top of Win32 and here the rules of Win32 are being reflected on to you.

The documentation for SetForegroundWindow gives a comprehensive explanation of the issue you face. Essentially the issue facing the design of SetForegroundWindow is that it can be used for focus stealing. Focus is something that users should control. Applications that change the focus can be troublesome. And so SetForegroundWindow attempts to defend against focus stealers.

The documentation says:

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

  • The process is the foreground process.
  • The process was started by the foreground process.
  • The process received the last input event.
  • There is no foreground process.
  • The process is being debugged.
  • The foreground process is not a Modern Application or the Start Screen.
  • The foreground is not locked (see LockSetForegroundWindow).
  • The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
  • No menus are active.

An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.

You are almost surely falling foul of these criteria. Note that a process that is being debugged is always granted permission to set foreground window. That explains why you see no problems whilst debugging. But outside a debugger, if your process is not the foreground process, then calls to SetForegroundWindow fail.

This is all by design. Your reaction to this should be to try to come up with a design that doesn't require you to attempt to call SetForegroundWindow when your process is not the foreground process.

like image 200
David Heffernan Avatar answered Oct 17 '22 23:10

David Heffernan


Register a Hot Key with RegisterHotKey. Choose carefully the Hot Key, as you must not interfere with existing (or future) application.

When you need to steal the focus (but remember it's BAD), simulate the Hot Key with SendInput.

Then, you will receive a WM_HOTKEY message, and during the processing of that message, you will be allowed to use SetForegroundWindow (I mean, it will success).

You will have to store/remenber somewhere the HWND of the window to activate, between the call to SendInput and your processing of WM_HOTKEY, which is posted.

References: Pressing a registered hotkey gives you the foreground activation love

like image 44
manuell Avatar answered Oct 18 '22 01:10

manuell