Как препятствовать закрыться-gridview, когда сценарий заканчивается

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

"hello world" | out-gridview

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

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

7
задан TN. 19 January 2010 в 23:05
поделиться

1 ответ

Вы можете либо запустить PowerShell.exe с -NOEXIT или попробуйте:

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

Обновлено: Out-GridView неблокирует, поэтому, если вы хотите проверить для него, чтобы выйти, вы должны прибегать к некоторому низкоуровневым API-APIS Win32. Следующий код работает в ISE (не проверил его в хосте консоли). Также он имеет ограничение - в основном ищет любое окно, связанное с процессом HOST, кроме главного окна хоста, чтобы уйти. В этот момент он вернется. Оказывается, out-gridview не ребенок главного окна, а его подпись не последовательно (gps | out-gridview или gps | ogv или gps | <Любые псевдонима, которые вы составляете> ):

$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!!!!"
4
ответ дан 6 December 2019 в 10:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: