Powershell - Close Out-GridView after specific time

家住魔仙堡 提交于 2020-01-14 07:00:30

问题


I want that a Out-GridView closes after a specific time, e.g after 10 seconds.

Not used to the windows powershell.

Any answer helps.


回答1:


Unfortunately, PowerShell doesn't natively offer finding and closing arbitrary GUI windows, but you can use the Add-Type cmdlet with ad hoc-compiled C# code that in turn uses P/Invoke declarations to access the Windows API.

The following is a working example:

  • It defines a distinct window title to use for the Out-GridView call so that the window can be (hopefully) unambiguously located by its title later; also the assumption is that only one window by that title exists.

    • To make this more robust by limiting the window search to the same process, ... would require quite a bit of extra work.
  • It creates a background job that uses Add-Member to define a static helper class with a method for closing a window by its title, and calls it after a specifiable timeout.

  • It invokes Out-GridView synchronously (blocking) with -Wait, using the specified window title. If the window is left open for the specified timeout period, the background job will automatically close it.

  • It removes the background job after the window has closed.

Note: If you don't need the Out-GridView call to be synchronous, you wouldn't necessarily need a background job.

# 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


来源:https://stackoverflow.com/questions/51542186/powershell-close-out-gridview-after-specific-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!