Как предотвратить закрытие out-gridview после завершения скрипта - PullRequest
7 голосов
/ 20 января 2010

У меня есть скрипт, который представляет результаты, используя out-gridview. Вот простой пример:

"hello world" | out-gridview

Когда я запускаю скрипт, используя Запустить с PowerShell , он откроет gridview и закроет его сразу после его открытия. (Я думаю, это потому, что gridview не является модальным, и скрипт завершается.)

Как заставить PowerShell ждать, пока вид сетки будет закрыт вручную?

Ответы [ 4 ]

7 голосов
/ 21 августа 2015

Как насчет:

"hello world" | out-gridview -wait

В соответствии с документацией Out-GridView, опция -Wait запрещает закрытие Windows PowerShell до закрытия окна Out-GridView.

Доступен в Windows PowerShell 3.0.

6 голосов
/ 13 марта 2014

Я знаю, старый вопрос, но ....

Просто добавьте «-PassThru» в Out-Gridview - добавьте кнопки «OK» и «Отмена» в сетку - теперь вы можете «запустить с powershell» и закрыть окно сетки, используя кнопку OK, когда вы закончите - тааак гораздо проще!

4 голосов
/ 20 января 2010

Вы можете запустить Powershell.exe с -noexit или попробовать это:

"hello world" | out-gridview
Read-Host "press enter to exit"

ОБНОВЛЕНО: Out-GridView не блокируется, поэтому, если вы хотите проверить егодля выхода нужно прибегнуть к некоторым низкоуровневым API Win32.Следующий код работает в ISE (не проверял его на хосте консоли).Также у него есть ограничение - он в основном ищет любое окно, связанное с хост-процессом, кроме основного окна хост-процесса.В этот момент он вернется.Оказывается, что Out-GridView не является дочерним элементом основного окна, и его заголовок не согласован (GPS | Out-GridView или GPS | ogv или GPS | <any alias you make up>):

$src = @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace Utils
{
    public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

    public class WindowHelper 
    {
        private const int PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
        private IntPtr _mainHwnd;
        private IntPtr _ogvHwnd;
        private IntPtr _poshProcessHandle;
        private int _poshPid;
        private bool _ogvWindowFound;

        public WindowHelper()
        {
            Process process = Process.GetCurrentProcess();
            _mainHwnd = process.MainWindowHandle;
            _poshProcessHandle = process.Handle;
            _poshPid = process.Id;
        }

        public void WaitForOutGridViewWindowToClose()
        {
            do 
            {
                _ogvWindowFound = false;
                EnumChildWindows(IntPtr.Zero, EnumChildWindowsHandler,
                                 IntPtr.Zero);
                Thread.Sleep(500);
            } while (_ogvWindowFound);
        }

        [DllImport("User32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumChildWindows(
            IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

        [DllImport("Oleacc.dll")]
        public static extern IntPtr GetProcessHandleFromHwnd(IntPtr hwnd);

        [DllImport("Kernel32.dll")]
        public static extern int GetProcessId(IntPtr handle);

        [DllImport("Kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DuplicateHandle(
            IntPtr hSourceProcessHandle, 
            IntPtr hSourceHandle, 
            IntPtr hTargetProcessHandle,
            out IntPtr lpTargetHandle,
            int dwDesiredAccess,
            bool bInheritHandle,
            int dwOptions);

        [DllImport("Kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr handle);

        [DllImport("Kernel32.dll")]
        public static extern int GetLastError();

        private bool EnumChildWindowsHandler(IntPtr hwnd, IntPtr lParam)
        {
            if (_ogvHwnd == IntPtr.Zero)
            {
                IntPtr hProcess = GetProcessHandleFromHwnd(hwnd);
                IntPtr hProcessDup;
                if (!DuplicateHandle(hProcess, hProcess, _poshProcessHandle,
                                     out hProcessDup, 
                                     PROCESS_QUERY_LIMITED_INFORMATION,
                                     false, 0))
                {
                    Console.WriteLine("Dup process handle {0:X8} error: {1}",
                                      hProcess.ToInt32(), GetLastError());
                    return true;
                }
                int processId = GetProcessId(hProcessDup);
                if (processId == 0)
                {
                    Console.WriteLine("GetProcessId error:{0}",
                                      GetLastError());
                    return true;
                }
                if (processId == _poshPid)
                {
                    if (hwnd != _mainHwnd)
                    {
                        _ogvHwnd = hwnd;
                        _ogvWindowFound = true;
                        CloseHandle(hProcessDup);
                        return false;
                    }
                }
                CloseHandle(hProcessDup);
            }
            else if (hwnd == _ogvHwnd)
            {
                _ogvWindowFound = true;
                return false;
            }
            return true;
        }
    }
}
'@

Add-Type -TypeDefinition $src

Get-Process | Out-GridView

$helper = new-object Utils.WindowHelper
$helper.WaitForOutGridViewWindowToClose()

"Done!!!!"
2 голосов
/ 31 марта 2011

Решение Кейта у меня почему-то не работает. Когда я запускаю его, я получаю ошибки, и процесс завершается, не дожидаясь закрытия сетки. Я получаю вывод, как это:

...
GetProcessId error:6
Dup process handle 0000015C error: 6
GetProcessId error:6
GetProcessId error:6
Dup process handle 00000148 error: 6
GetProcessId error:6
GetProcessId error:6
...

Я не очень хорошо понимаю Windows API, используемый в решении Кейта. Но после некоторого поиска я нашел способ изменить решение, которое проще. Он включает в себя меньше вызовов и импортов API и также не вызывает ошибок. Это то, что я придумал.

$src = @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace Utils
{
  public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

  public class WindowHelper
  {
    private const int PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
    private IntPtr _mainHwnd;
    private IntPtr _ogvHwnd;
    private IntPtr _poshProcessHandle;
    private int _poshPid;
    private bool _ogvWindowFound;

    public WindowHelper()
    {
      Process process = Process.GetCurrentProcess();
      _mainHwnd = process.MainWindowHandle;
      _poshProcessHandle = process.Handle;
      _poshPid = process.Id;
    }

    public void WaitForOutGridViewWindowToClose()
    {
      do
      {
        _ogvWindowFound = false;
        EnumChildWindows(IntPtr.Zero, EnumChildWindowsHandler,
                 IntPtr.Zero);
        Thread.Sleep(500);
      } while (_ogvWindowFound);
    }

    [DllImport("User32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(
      IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

    [DllImport("User32.dll")]
    public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);

    [DllImport("Kernel32.dll")]
    public static extern int GetLastError();

    private bool EnumChildWindowsHandler(IntPtr hwnd, IntPtr lParam)
    {
      if (_ogvHwnd == IntPtr.Zero)
      {
        int processId;
        int thread = GetWindowThreadProcessId(hwnd, out processId);

        if (processId == 0)
        {
          Console.WriteLine("GetWindowThreadProcessId error:{0}",
                   GetLastError());
          return true;
        }
        if (processId == _poshPid)
        {
          if (hwnd != _mainHwnd)
          {
            _ogvHwnd = hwnd;
            _ogvWindowFound = true;
            return false;
          }
        }
      }
      else if (hwnd == _ogvHwnd)
      {
        _ogvWindowFound = true;
        return false;
      }
      return true;
    }
  }
}
'@

Add-Type -TypeDefinition $src

Get-Process | Out-GridView       
$helper = new-object Utils.WindowHelper 
$helper.WaitForOutGridViewWindowToClose()

Надеюсь, это спасет кого-то еще от тех же проблем, что и у меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...