如果用户单击关闭('X')按钮,如何处理 PowerShell 窗口的关闭事件 [英] How to handle close event of PowerShell window if user clicks on Close('X') button

查看:85
本文介绍了如果用户单击关闭('X')按钮,如何处理 PowerShell 窗口的关闭事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 PowerShell 2.0 窗口关闭之前运行一些代码.为此,我尝试了:

I want to run some code before PowerShell 2.0 window is closed. For this I tried:

PS > register-engineevent PowerShell.Exiting -action {get-process |输出文件 c:\work\powershellexitevent called.txt}

如果用户使用 exit 命令(即 exit )关闭 PowerShell 窗口,它工作正常.但如果用户通过点击右上角的关闭('X')按钮关闭它,它就不起作用.

It works fine if user closes PowerShell window using exit command (i.e. exit ). But it does not work if user closes it by clicking on Close ('X') button on top right.

我找不到任何方法来处理这个问题.我也尝试通过以下方式进行操作,但这也不起作用:

I could not find any way to handle this. I also tried to do it the following way, but this does not work either:

PS > $query = "Select * from __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='powershell.exe'"

PS > $query = "Select * from __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='powershell.exe'"

PS > Register-WmiEvent -Query $query -Action {get-process |输出文件 c:\work\powershellexitevent called.txt}

PS > Register-WmiEvent -Query $query -Action {get-process | out-file c:\work\powershellexiteventcalled.txt}

请指导我如何完成这项任务.

Please guide how I can achieve this task.

更新:通过在线有用的专业人士的一些有用输入,我还尝试了以下操作:

UPDATE: With some useful input from a helpful professional online I also tried the following:

$appCurrentDomain = [System.AppDomain]::CurrentDomainRegister-ObjectEvent -Action {get-process |输出文件 c:\work\powershellexitevent called.txt} -InputObject $appCurrentDomain -EventName DomainUnload

$appCurrentDomain = [System.AppDomain]::CurrentDomain Register-ObjectEvent -Action {get-process | out-file c:\work\powershellexiteventcalled.txt} -InputObject $appCurrentDomain -EventName DomainUnload

但同样,它不起作用.根据微软的说法当 AppDomain 即将被卸载时,DomainUnload 事件发生.".但是当我关闭窗口时它不起作用(甚至为此输入 exit ).

But again, it does not work. As per Microsoft "DomainUnload event occurs when an AppDomain is about to be unloaded.". But it does not work when I close the window ( or even type exit for that matter).

更新:

在其他专业人士的帮助下,在线&我可以通过以下代码实现这一点.

With some help from other professionals online & a little effort I could achieve this with following code.

PS..> $code = @"

        using System;
        using System.Runtime.InteropServices;
        using System.Management.Automation;
        using System.Management.Automation.Runspaces;

        namespace MyNamespace
        {
            public static class MyClass
            {
                public static void SetHandler()
                {
                    SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
                }

                private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
                {
                    switch (ctrlType)
                    {
                        case CtrlTypes.CTRL_C_EVENT:
                            Console.WriteLine("CTRL+C received!");
                            return false;

                        case CtrlTypes.CTRL_CLOSE_EVENT:
                            Console.WriteLine("CTRL_CLOSE_EVENT received!");
                            return true;

                        case CtrlTypes.CTRL_BREAK_EVENT:
                            Console.WriteLine("CTRL+BREAK received!");
                            return false;

                        case CtrlTypes.CTRL_LOGOFF_EVENT:
                            Console.WriteLine("User is logging off!");
                            return false;

                        case CtrlTypes.CTRL_SHUTDOWN_EVENT:
                            Console.WriteLine("User is shutting down!");
                            return false;
                    }
                    return false;
                }

                [DllImport("Kernel32")]
                public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

                // A delegate type to be used as the handler routine
                // for SetConsoleCtrlHandler.
                public delegate bool HandlerRoutine(CtrlTypes CtrlType);

                // An enumerated type for the control messages
                // sent to the handler routine.
                public enum CtrlTypes
                {
                    CTRL_C_EVENT = 0,
                    CTRL_BREAK_EVENT,
                    CTRL_CLOSE_EVENT,
                    CTRL_LOGOFF_EVENT = 5,
                    CTRL_SHUTDOWN_EVENT
                }
            }
        }"@

PS..> $text = Add-Type  -TypeDefinition $code -Language CSharp
PS..> $rs = [System.Management.Automation.Runspaces.Runspace]::DefaultRunspace
PS..> [MyNamespace.MyClass]::SetHandler()      

但是我正面临一个问题....如果我在注册此处理程序后在控制台上运行任何 cmdlet(例如 get-date、get-process).然后,只要发生事件(例如 Ctrl+C、关闭),应用程序就会崩溃.有人可以帮我解决这个问题吗?

BUT THERES AN ISSUE I AM FACING.... If I run any cmdlet on console after registering this handler (e.g. get-date, get-process). Then the application will crash whenever an event occurs (e.g. Ctrl+C, close). Can someone please help me with this?

推荐答案

很遗憾,您不能这样做.退出事件将被调用的唯一时间是在 PowerShell 提示符下键入exit".

Unfortunately, you can't do this. The only time an exiting event will get called is if you type "exit" at the PowerShell prompt.

这是我如何连接退出事件:

This is how I hook up my exiting event:

 $null = Register-EngineEvent -SourceIdentifier `
     ([System.Management.Automation.PsEngineEvent]::Exiting) -Action { # Put code to run here }

这篇关于如果用户单击关闭('X')按钮,如何处理 PowerShell 窗口的关闭事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆