7
votes

Comment prévenir de la fermeture de la grille de sortie lorsqu'un script se termine

J'ai un script qui présente des résultats en utilisant Out-GridView . Voici un exemple simple: xxx

lorsque j'exécute le script à l'aide de exécuter avec PowerShell , il ouvrira la grille et la fermez immédiatement après son ouverture. (Je pense que c'est parce que GridView n'est pas modal et le script se termine.)

Comment faire de l'attente PowerShell jusqu'à ce que la grille soit fermée manuellement?


0 commentaires

5 Réponses :


4
votes

Vous pouvez soit exécuter PowerShell.exe avec -NOexit Essayez-le ou essayez ceci:

$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!!!!"


3 commentaires

Toute solution plus sophistiquée qui trouvera des fenêtres ouvertes et attendra jusqu'à ce qu'ils ferment?


J'ai corrigé deux problèmes avec le code source C # survenu lorsque je l'aurais posté à l'origine et le formaté ensuite pour s'adapter sans avoir besoin de barres de défilement.


Ne spécifierais pas le titre du titre de la fenêtre GridView en utilisant -title faire le processus de la recherche de plus simple?



3
votes

La solution de Keith ne fonctionne pas pour moi pour une raison quelconque. Lorsque je l'exécute, je reçois des erreurs et le processus se termine sans attendre que la grille se ferme. Je reçois une sortie comme ceci: xxx

Je ne comprends pas vraiment que l'API Windows est très bien utilisé dans la solution de Keith. Mais après quelques creux, j'ai trouvé un moyen de modifier la solution plus simple. Cela implique moins d'appels et d'importations d'API, et il ne produit aucune erreur non plus. C'est ce que je suis venu avec. xxx

Espérons que cela sauvera quelqu'un d'autre des mêmes problèmes que j'avais.


0 commentaires

6
votes

Il suffit d'ajouter -passthru à l'Out-GridView - ajoute un bouton "OK" et "Annuler" sur la grilleview - maintenant, vous pouvez "exécuter avec PowerShell" et fermer la fenêtre GridView en utilisant OK bouton lorsque vous avez terminé - soooo beaucoup plus simple!


1 commentaires

Ceci est uniquement disponible depuis PowerShell 3.0, qui a également introduit -Wait .



9
votes

Que diriez-vous: xxx

selon La documentation de Out-GridView , l'option -Wait empêche la fermeture de Windows PowerShell de la fermeture de la fenêtre Out-GridView.

Il est disponible dans Windows PowerShell 3.0.


0 commentaires

0
votes

Ceci gardera la fenêtre ouverte: xxx

ceci vous permet d'afficher la liste d'objets (par exemple) avec un titre et lorsque vous cliquez sur OK, il enregistre les données dans le presse-papiers.


0 commentaires