如何在事件发生后将GUI窗口放在最前面



正如标题所说,如果可能的话,在事件发生后,我如何将Powershell GUI窗口放在另一个窗口前面?例如,我打开了Firefox,Powershell GUI在它后面运行,在Powershell内部发生某个事件后,它会弹出到Firefox前面吗?

在Windows上,您可以使用[Microsoft.VisualBasic.Interaction]::AppActivate()通过进程ID重新激活您自己的进程主窗口,如自动$PID变量所示

# 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)

注:

  • 常规跨进程边界的任意窗口的程序激活在默认情况下被阻止:

    • 目标窗口不是被激活,而是其任务栏按钮闪烁,以便向用户发出激活窗口的意图

    • 但是,似乎总是允许从当前前台窗口中运行的代码进行编程激活

  • 上面的Add-Type-MemberDefinition调用通过将其SPI_SETFOREGROUNDLOCKTIMEOUT参数设置为0,使用对SystemParametersInfoWinAPI函数的p/Invoke调用来覆盖当前会话的

    • 这将导致每次会话的一次性编译性能损失。

    • 对于所有进程,将在会话的剩余时间启用跨进程窗口激活。

    • [在W10+中不再工作]另一种选择是通过注册表持久地配置您的用户帐户以允许激活:

      • HKEY_CURRENT_USERControl PanelDesktop中的ForegroundLockTimeout每用户注册表值设置为0(默认值为200000毫秒,即3分20秒(;需要注销或重新启动更改才能生效:

        Set-ItemProperty 'registry::HKEY_CURRENT_USERControl PanelDesktop' ForegroundLockTimeout 0
        

最新更新