Refer to the MSDN documentation for SetForegroundWindow
Windows intentionally refuses many requests to set a particular window to foreground, with the stated goal that:
An application cannot force a window to the foreground while the user is working with another window.
The conditions under which SetForegroundWindow will succeed are documented as:
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.
This documentation does not sound correct. I believe that it started as a shorter list, in which only one of the conditions needed to be met. But the actual behavior is more complex.
Can anyone confirm the actual behavior? Is it:
A process can set the foreground window only if all the following hold:
One or more of the following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process was identified in an AllowSetForegroundWindow call made 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.
One of the following two conditions is true:
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
If other experts concur that the documentation is erroneous here, I will file a bug report on Connect referencing this question.
Related
I am using a script that:
Launches Thunderbird
Creates a new message
Minimizes the message box
Copies the path to the selected folder
How to activate a minimized Thunderbird message box, knowing its Title?
The code below does not work:
Set WshShell = CreateObject("WScript.Shell")
Set WshExec = WshShell.Exec("""C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe""")
WScript.Sleep 2000
WshShell.SendKeys("^n")
WScript.Sleep 500
PID = WshShell.AppActivate(WshExec.ProcessID)
WshShell.Run("notepad")
If PID Then
WshShell.SendKeys("^k")
Else
MsgBox "Nothing!"
End If
VBS's AppActivate wraps the API's SetForegroundWindow. Your program MUST comply with one of the following rules to set the active window. Note the standard lockout time is 2 seconds - which is where most people get caught. Note VBScript has no user interface so cannot be the foreground window - you have 2 seconds to set windows after your program starts.
From https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setforegroundwindow
SetForegroundWindow
Remarks
The foreground window is the window at the top of the Z order. It is
the window that the user is working with. In a preemptive multitasking
environment, you should generally let the user control which window is
the foreground window.
Windows 98/Me, Windows 2000/XP: 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 foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.
With this change, an application cannot force a window to the
foreground while the user is working with another window. Instead,
SetForegroundWindow will activate the window (see SetActiveWindow) and
call the FlashWindowEx function to notify the user.
We have a very critical process that needs to be monitored. If it crashes for some reason the admin needs immediate notification. We have tried different scenario's but none work for their own reasons:
VBScript SELECT * FROM Win32_Process WHERE Name LIKE '%IPRUN%'
This doesn't work because the process doesn't exit on crash it goes a WER window. So when you hit close in WER window only then the process exits (i.e. disappears from the task manager) so until the process doesn't disappear this code is useless.
EventViewer: The application produces Start and Close events but does not for crashed events (for reasons understood) as application thread has exited abnormally, and might be its handled in an unusal way
Is there any other way of monitoring this?
When I debug my program, which consists of looping over thousands of entries in vectors multiple times, it simply freezes the program but does not provide any error messages whatsoever. Does Visual Studio have some sort of auto-time out that I am experiencing?
Check may be your program is going into infinite loop Or doing some heavy task that makes your UI unresponsive(if you have windows form). Since you are debugging this program then why dont you set breakpoint in code and check where your program is causing issue.
And yes there is no time out for Visual Studio,But for program window.This is known as Hang Status.
When an application (or more accurately, a thread) creates a window on the desktop, it enters into an implicit contract with the Desktop Window Manager (DWM) to process window messages in a timely fashion. The DWM posts messages (keyboard/mouse input and messages from other windows, as well as itself) into the thread-specific message queue. The thread retrieves and dispatches those messages via its message queue. If the thread does not service the queue by calling GetMessage(), messages are not processed, and the window hangs: it can neither redraw nor can it accept input from the user. The operating system detects this state by attaching a timer to pending messages in the message queue. If a message has not been retrieved within 5 seconds, the DWM declares the window to be hung. You can query this particular window state via the IsHungAppWindow() API.
Detection is only the first step. At this point, the user still cannot even terminate the application - clicking the X (Close) button would result in a WM_CLOSE message, which would be stuck in the message queue just like any other message. The Desktop Window Manager assists by seamlessly hiding and then replacing the hung window with a 'ghost' copy displaying a bitmap of the original window's previous client area (and adding "Not Responding" to the title bar). As long as the original window's thread does not retrieve messages, the DWM manages both windows simultaneously, but allows the user to interact only with the ghost copy. Using this ghost window, the user can only move, minimize, and - most importantly - close the unresponsive application, but not change its internal state.
A nice article is written in this following link.
How program window works
I have VSTO addins for Office (Excel / Word / Outlook) 2007 / 2010. Through the use of the NativeWindow the office programs listen for Hotkeys. Upon hotkey recognition a message (WinApi SendMessage) is sent to my own application which then uses the SetForegroundWindow SetForegroundWindow(Hwnd) function to bring Internet Explorer to the front. This works fairly well on most occasions but sometimes it does not. When it does not work the office application is left in front and the Internet Explorer icon is flashing in the task bar.
I am aware that this is by design from Microsoft for the SetForegroundWindow function to stop malicious code.
I do not know exactly why it works sometimes and not others but think it is because the user is using the keyboard to enter the hotkeys and thus the Office application does not want to give up this focus.
My first thought was to simply minimize the Office program but I do not want to do this as some people have multiple screens with Internet Explorer on one and the office application on the other.
When my VSTO addin receives the hotkey signal I would like the office application to relinquish being the foreground or active window, but I do not want it to be minimized.
I know the last paragraph might not be a correct question so maybe more generally as the VSTO addin is working with the Office application process what can I do here so that a call to SetForegroundWindow will work.
Edit: To be clear the only code I am using so far is SetForegroundWindow(Hwnd) where the Hwnd is that of Internet Explorer. As the conditions are now posted I am interested in creating the condition "There is no foreground process"
From the documentation:
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. [Emphasis Mine]
How do you know if you successfully set the foreground window?
If the window was brought to the foreground, the return value is nonzero.
If the window was not brought to the foreground, the return value is zero.
Without any code to go on, there's no way to know which is causing the problem.
When I run the following script via CMD.EXE the display of Word is normal i.e. Maximized.
Set oWord = CreateObject("Word.Application")
oWord.Visible = True
oWord.Documents.open(sTempWordFile)
oWord.Run WScript.Arguments.item(0)
oWord.Activate
When I call the same script as Target in a shortcut .LNK file the display is always minimized!
The .LNK file target is: "%OWNERS_CORP_ROOT%\cmd\RunWord.vbs" memos
Using Windows 8.1, Office 2013. Shortcut .LNK file is set to Run 'Maximized'.
How do I make a 'Maximized' display when using the shortcut?
SetForegroundWindow Function
The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user. The system assigns a slightly higher priority to the thread that created the foreground window than it does to other threads.
Syntax
BOOL SetForegroundWindow( HWND hWnd
);
Parameters
hWnd
[in] Handle to the window that should be activated and brought to the foreground.
Return Value
If the window was brought to the foreground, the return value is nonzero.
If the window was not brought to the foreground, the return value is zero.
Remarks
Windows 98/Me: 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 foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.
With this change, an application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user. However, on Microsoft Windows 98 and Windows Millennium Edition (Windows Me), if a nonforeground thread calls SetForegroundWindow and passes the handle of a window that was not created by the calling thread, the window is not flashed on the taskbar. To have SetForegroundWindow behave the same as it did on Windows 95 and Microsoft Windows NT 4.0, change the foreground lock timeout value when the application is installed. This can be done from the setup or installation application with the following function call:
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
This method allows SetForegroundWindow on Windows 98/Windows Me and Windows 2000/Windows XP to behave the same as Windows 95 and Windows NT 4.0, respectively, for all applications. The setup application should warn the user that this is being done so that the user isn't surprised by the changed behavior. On Windows Windows 2000 and Windows XP, the call fails unless the calling thread can change the foreground window, so this must be called from a setup or patch application. For more information, see Foreground and Background Windows.
A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.
The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.
Function Information
Minimum DLL Version user32.dll
Header Declared in Winuser.h, include Windows.h
Import library User32.lib
Minimum operating systems Windows 95, Windows NT 3.1
Unicode Implemented as Unicode version.
See Also
Windows Overview, AllowSetForegroundWindow, FlashWindowEx, GetForegroundWindow, LockSetForegroundWindow, SetActiveWindow