I want to run some code before closing the PowerShell 2.0 window. For this, I tried:
PS> register-engineevent PowerShell.Exiting -action {get-process | out-file c: \ work \ powershellexiteventcalled.txt}
It works great if the user closes the PowerShell window using the exit (i.e. exit) command. But this does not work if the user closes it by clicking the "Close" ("X") button in the upper right corner.
I could not find a way to handle this. I also tried to do it as follows, but this also does not work:
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 | out-file c: \ work \ powershellexiteventcalled.txt}
Please indicate how I can achieve this.
UPDATE: With some useful results from a useful professional online, I also tried the following:
$ appCurrentDomain = [System.AppDomain] :: CurrentDomain Register-ObjectEvent -Action {get-process | out-file c: \ work \ powershellexiteventcalled.txt} -InputObject $ appCurrentDomain -EventName DomainUnload
But then again, this will not work. According to Microsoft, "The DomainUnload event occurs when the AppDomain is about to unload." But this will not work when I close the window (or even the type of exit, for that matter).
UPDATE:
With some help from other professionals on the Internet and a little effort, I could achieve this with the 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()
BUT WHY IS ISSUE I LOVE .... If I run any cmdlet on the console after registering this handler (for example, get-date, get-process). Then the application will crash on every event (e.g. Ctrl + C, close). Can someone please help me with this?