Reputation: 11
As the title says, how can I bring a Powershell GUI window in front of another window after an event has happened, if it is at all possible? As in, I have, for example, Firefox opened and the Powershell GUI is running behind it, after certain event happens inside of the Powershell it pops in front of the Firefox?
Upvotes: 1
Views: 971
Reputation: 439597
On Windows, you can use [Microsoft.VisualBasic.Interaction]::AppActivate()
to reactivate your own process' main window via the process ID, as reflected in the automatic $PID
variable:
# Enable cross-process window activation (see below).
(Add-Type -ErrorAction Stop -PassThru -Namespace "Random.Ns$PID.AllowWindowActivation" -Name WinApiHelper -MemberDefinition @'
[DllImport("user32.dll", EntryPoint="SystemParametersInfo")]
static extern bool SystemParametersInfo_Set_UInt32(uint uiAction, uint uiParam, UInt32 pvParam, uint fWinIni);
public static void AllowWindowActivation()
{
if (! SystemParametersInfo_Set_UInt32(0x2001 /* SPI_SETFOREGROUNDLOCKTIMEOUT */, 0, 0 /* timeout in secs */, 0 /* non-persistent change */)) {
throw new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error(), "Unexpected failure calling SystemParametersInfo() with SPI_SETFOREGROUNDLOCKTIMEOUT");
}
}
'@)::AllowWindowActivation()
# Load the required assembly.
Add-Type -AssemblyName Microsoft.VisualBasic
# Launch a sample GUI application that will steal the focus
# (will become the foreground application).
Start-Process notepad.exe
# Wait a little.
Start-Sleep 3
# Now reactivate the main window of the current process.
[Microsoft.VisualBasic.Interaction]::AppActivate($PID)
Note:
General programmatic activation of arbitrary windows across process boundaries is prevented by default:
Instead of the targeted window getting activated, its taskbar button flashes, so as to signal to the user the intent to make the window active.
However, programmatic activation from code running in the current foreground window seems to always be permitted.
The Add-Type
-MemberDefinition
call above overrides this for the current session using a P/Invoke call to the SystemParametersInfo
WinAPI function, via setting its SPI_SETFOREGROUNDLOCKTIMEOUT
parameter to 0
.
This will incur a one-time compilation performance penalty per session.
Cross-process window activation will be enabled for the remainder of the session, for all processes.
[Doesn't work anymore in W10+] The alternative is to persistently configure your user account to allow activation, via the registry:
Set the ForegroundLockTimeout
per-user registry value in HKEY_CURRENT_USER\Control Panel\Desktop
to 0
(the default is 200000
msecs., i.e. 3 minutes and 20 secs); requires logging off or rebooting for the change to take effect:
Set-ItemProperty 'registry::HKEY_CURRENT_USER\Control Panel\Desktop' ForegroundLockTimeout 0
Upvotes: 2