Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow background application to set foreground window of different process

First off, I know this is a controversal discussion but I hope we can keep this technical.

I have an application which is started in background and I somehow want it to be able to activate/bring to focus a window in a different process. But calling SetForegroundWindow always fails even if the process whose window I want to activate has called AllowSetForegroundWindow(ASFW_ANY).

The reason is (IMO) that the initiating application is a background process and since it has not received the input it is not allowed to set foreground window. So everything appears in the tasklist but it is not shown.

So I tried creating a dummy window to receive input which is closed immideately and afterwards be able to call SetForegroundWindow successfully. But even the dummy window I display is displayed in background.

However, if I call

AttachThreadInput(
    GetWindowThreadProcessId(GetForegroundWindow(), NULL),
    GetCurrentThreadId(), TRUE);

before creating the dummy window, the window is indeed created in foreground and I can afterwards call SetForegroundWindow for a different HWND in a different process which works.

BUT: If I do not create the dummy window, SetForegroundWindow still returns zero although I use AttachThreadInput.

I don't understand why the AttachThreadInput hack is successful if I create an own Window (and successds for other windows afterwards) but is unsuccessful if I do not create an own window first.

How can my background process call SetForegroundWindow on a different window in a different process without creating a dummy window?

[*] The background application is actually gpg-agent.exe which calls pinentry.exe (my application) whenever a password is requested. pinentry.exe (running as background process) must request the password from another running application, therefore it must bring its window to foreground ...

like image 252
divB Avatar asked Nov 22 '22 20:11

divB


1 Answers

The documentation for AttachThreadInput() gives you a clue:

Windows created in different threads typically process input independently of each other. That is, they have their own input states (focus, active, capture windows, key state, queue status, and so on), and their input processing is not synchronized with the input processing of other threads. By using the AttachThreadInput function, a thread can attach its input processing mechanism to another thread. Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo parameter until the threads are detached by calling AttachThreadInput a second time and specifying FALSE for the fAttach parameter. This also allows threads to share their input states, so they can call the SetFocus function to set the keyboard focus to a window of a different thread. This also allows threads to get key-state information.

The documentation for SetForegroundWindow() tells you what criteria the calling process needs to meet in order to set a foreground window:

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.

Simply creating a dummy window by itself does not guarantee that you will become the foreground process. Attaching your window's thread to the current foreground window's thread allows you to share its input state, which gives you a better chance of gaining permission to set a foreground window if the foreground thread has permission to do so.

like image 112
Remy Lebeau Avatar answered Nov 25 '22 11:11

Remy Lebeau