Powershell-在特定时间后关闭Out-GridView

时间:2018-07-26 15:11:50

标签: windows powershell grid

我希望Out-GridView在特定时间(例如10秒)后关闭。

不习惯Windows powershell。

任何答案都有帮助。

1 个答案:

答案 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