5

Hi i have a monitoring script (with a winforms gui) that is always running in the back. Unfortunately this annoys users when they try to manually shutdown the computer, cause it provokes the "this app is preventing windows shutdown"-screen.

So i need a a reliable way to automatically close the script when a shutdown was initiated.

I tried subscribing to the SessionEnding- and SessionEnded-event, but it did not work:

$sysevent = [microsoft.win32.systemevents]
Register-ObjectEvent -InputObject $sysevent -EventName "SessionEnding" -Action { Exitfunction }

UPDATE: Its like this at the moment:

$sysevent = [microsoft.win32.systemevents]
Register-ObjectEvent -InputObject $sysevent -EventName "SessionEnding" -Action { [Windows.Forms.MessageBox]::Show("Shutdown!", "", [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Warning)}
Register-ObjectEvent -InputObject $sysevent -EventName "SessionEnded" -Action { [Windows.Forms.MessageBox]::Show("Shutdown!", "", [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Warning)}
Register-WmiEvent -Class win32_computerShutdownEvent -Action { [Windows.Forms.MessageBox]::Show("Shutdown!", "", [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Warning)}

I added a messagebox to see if one of these events would in fact fire, but maybe the code executed by the action scriptblock was faulty. No luck. None of these events kick in when i try to shutdown a windows 8.1 system. There are no errors inside the events when i read them with get-job. The state is in all of them "not started".

Any ideas why?

Rob
  • 472
  • 4
  • 17
  • Possible duplicate of [Powershell window preventing shutdown](http://stackoverflow.com/questions/10174075/powershell-window-preventing-shutdown) – Ken White Jan 22 '16 at 00:05
  • Thats the same solution i posted myself above. It did not work, at least not every time. Unfortunately i can not say WHY it did not work, so i'm looking for an alternative solution, if there is one. – Rob Jan 22 '16 at 00:08
  • Um, no. It's not. The linked post contains significantly more code than what you posted here, and includes registering for a second event as well. You should probably read it more carefully. (It's also been accepted, which typically means that the user who asked the question found the solution to work.) – Ken White Jan 22 '16 at 00:10
  • Yes it has more code, but only code that is executed AFTER the event has succesfully been raised. So its not important to the the task. I tried the second event as well, it did not help.I'll add that in the OP. – Rob Jan 22 '16 at 00:15

3 Answers3

4

The following code is not an answer to your full question, but it is to your title question, and may help someone who just wants to stop a shutdown already timing out:

If ( [ System.Environment ]:: HasShutdownStarted ) {
  & "$env:SystemRoot\System32\Shutdown.exe" -a ;
}

I use spaces whenever possible and semicolons to bring more clarity to me.

2

OK the solution is: If a shutdown is initiated, Windows send a WM_QUIT-Message to all applications. If you subscribe to the onClosing-event, you can query the $eventargs if that event has been fired. It contains a CloseReason-property, which if it is WindowsShutdown can be used to initiate a proper cleanup and close down of the app. See the answer to this post for more info on how to do that.

Community
  • 1
  • 1
Rob
  • 472
  • 4
  • 17
0

have you looked at this article?

https://web.archive.org/web/20150424054433/http://blogs.technet.com/b/heyscriptingguy/archive/2010/04/15/hey-scripting-guy-april-15-2010.aspx

he uses wmi to watch for the event Register-WmiEvent -Class win32_computerShutdownEvent

mklement0
  • 382,024
  • 64
  • 607
  • 775
Hiker86
  • 76
  • 8
  • Thanks, I'll try that. – Rob Jan 22 '16 at 00:16
  • As of Aug.2020 the link has been changed to https://devblogs.microsoft.com/scripting/hey-scripting-guy-can-i-use-wmi-to-determine-when-someone-logs-off-a-user-or-shuts-down-a-server/ – rs232 Aug 19 '20 at 09:48