你们再做些什么,要求温和会呼吁:
# Helper type for various windows-related WinAPI functions.
Add-Type -Namespace Util -Name WinApi -MemberDefinition @
// The callback delegate, which receives:
// - the hWnd being enumerated
// - a custom LPARAM value passed on invocation to EnumWindows()
// The delegate must return $true to keep enumerating; in other words: $false stops the enumeration.
// Note the custom ArrayList parameter in lieu of an IntPtr (LPARAM) (using a generic list is NOT an option, because generic types cannot be marshalled).
public delegate bool EnumWindowsProc(IntPtr hWnd, System.Collections.ArrayList lParam);
// The EnumWindows() API function that enumerates *top-level windows*.
// It too uses a custom ArrayList parameter instead of the IntPtr (LPARAM), which the callback receives.
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, System.Collections.ArrayList lParam);
// Get the class name of a window by its handle.
[DllImport("user32.dll")]
public static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder classNameBuf, int nMaxCount);
// Cascade the specified window(s).
[DllImport("user32.dll")]
public static extern ushort CascadeWindows(IntPtr hwndParent, uint wHow, IntPtr lpRect, uint cKids, IntPtr[] lpKids);
// Show the specified window.
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// Make the specified window the foreground window, if allowed (see below).
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
// Allow making the windows of other processes the foreground window
// for the remainder of the session.
[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");
}
}
@
# Get all Notepad windows, on the assumption that their window class name is Notepad .
[System.Collections.ArrayList] $matchingHwnds = @()
[Util.WinApi]::EnumWindows(
{ # delegate (callback function)
param([intptr] $hWnd, [System.Collections.ArrayList] $param)
$sb = [System.Text.StringBuilder]::new(1024)
$null = [Util.WinApi]::GetClassName($hWnd, $sb, $sb.Capacity-1)
if ($sb.ToString() -eq Notepad ) {
$param.Add($hWnd)
}
return $true # continue enumerating
},
$matchingHwnds # the array list to pass as custom data
)
# Reverse the matching window handles (if any).
[IntPtr[]] $matchingHwndsInReverse = [Linq.Enumerable]::Reverse([IntPtr[]] $matchingHwnds)
# Make sure all windows are restored (non-minimized, non-maximized), in reverse order.
foreach ($hwnd in $matchingHwndsInReverse) {
$null = [Util.WinAPI]::ShowWindow($hwnd, 1)
}
# Cascade them.
$null = [Util.WinAPI]::CascadeWindows([IntPtr]::Zero, 0, [IntPtr]::Zero, $matchingHwnds.Count, $matchingHwnds)
# Activate them in reverse order.
# First, enable cross-process window activation...
[Util.WinAPI]::AllowWindowActivation()
# ... then activate them.
foreach ($hwnd in $matchingHwndsInReverse) {
$null = [Util.WinAPI]::SetForegroundWindow($hwnd)
}