Powershell - закрывает Out-GridView через определенное время

Я хочу, чтобы Out-GridView закрывался через определенное время, например, через 10 секунд.

Не используется для Windows PowerShell.

Любой ответ помогает.

1 ответ

К сожалению, PowerShell не предлагает поиск и закрытие произвольных окон графического интерфейса, но вы можете использовать Add-Type Командлет с ad-hoc-скомпилированным кодом 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
Другие вопросы по тегам