我希望Out-GridView在特定时间(例如10秒)后关闭。
不习惯Windows powershell。
任何答案都有帮助。
答案 0 :(得分:1)
不幸的是,PowerShell本身不提供查找和关闭任意GUI窗口的功能,但是您可以将Add-Type
cmdlet与临时编译的C#代码一起使用,而C#代码又使用P / Invoke声明来访问Windows API。
以下是一个有效的示例:
它定义了一个用于Out-GridView
调用的独特窗口标题,以便以后可以(希望)通过其标题明确地定位该窗口;还假设只有那个标题的一个窗口存在。
它创建一个后台作业,该作业使用Add-Member
定义一个静态帮助器类,该类具有通过其标题关闭窗口的方法,并在指定的超时后调用它。
它使用指定的窗口标题与Out-GridView
同步调用-Wait
(阻塞)。如果窗口在指定的超时时间内保持打开状态,则后台作业将自动将其关闭。
它在关闭窗口后删除后台作业。
注意:如果不需要同步Out-GridView
调用,则不一定需要后台作业。
# Define a distinct window title that you expect no other window to have.
$title = 'Close Me'
# Start a background job that closes the window after a specified timeout.
$job = Start-Job {
param($timeout, $title)
# Define a helper class that uses the Windows API to find and close windows.
Add-Type -Namespace same2u.net -Name WinUtil -MemberDefinition @'
// P/Invoke declarations for access to the Windows API.
[DllImport("user32.dll", SetLastError=true)]
private static extern IntPtr FindWindow(string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError=true)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
const UInt32 WM_CLOSE = 0x0010;
// Returns the hWnd (window handle) of the first window that matches the
// specified title and, optionally, window class.
// If none is found, IntPtr.Zero is returned, which can you test for with -eq 0
public static IntPtr GetWindowHandle(string title, string className = null) {
// As a courtesy, we interpet '' as null, because passing null from
// PowerShell requires the non-obvious [nullstring]::value.
if (className == "") { className = null; }
return FindWindow(className, title);
}
// Closes the first window that matches the specified title and, optionally,
// window class. Returns true if a windows found and succesfully closed.
public static bool CloseWindow(string title, string className = null) {
bool ok = false;
// As a courtesy, we interpet '' as null, because passing null from
// PowerShell requires the non-obvious [nullstring]::value.
if (className == "") { className = null; }
IntPtr hwnd = FindWindow(className, title);
if (hwnd != IntPtr.Zero) {
SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
// !! SendMessage seemingly always returns 0. To determine success,
// !! we simply test if the window still exists.
ok = IntPtr.Zero == FindWindow(className, title);
}
return ok;
}
'@
Start-Sleep $timeout
$null = [same2u.net.WinUtil]::CloseWindow($title)
} -ArgumentList 3, $title
# Open an Out-GridView window synchronously.
# If you leave it open, the background job will close it after 3 seconds.
1..10 | Out-GridView -Title $title -Wait
# Remove the background job; -Force is needed in case the job hasn't finished yet
# (if you've closed the window manually before the timeout).
Remove-Job -Force $job