So, how did I screw up a program so massively for it to prevent shutdown? Actually, it was really simple. For developers, this is a warning message about the problems of cancelling the closing of your window without taking all things in account.
The Problem
Software Updater consists of a few forms, but the important one is the main window. On the main window is a NotifyIcon object, the object which I can use to give my program a constant presence in the notification area.(This is a bad idea for reasons Raymond Chen lists, but really, that’s beside the point, and the same problem would exist anyway, since that form also contains the code to check updates. I will be removing the superfluous icon in a later version anyway, so, yuh.)
Now, I wanted to keep the form open when someone clicked the close button, so it could do its business. I’d hide it from the user, but it would still be there, running the stuff it needed to run.
After a poke around the form’s FormClosing event, I decided to use the following code:
Private Sub Main_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosingSee the problem yet?
e.Cancel = True
Me.Visible = False
End Sub
The problem is that every time anything tries to close the form, whether it’s hidden or not, this code will execute. The window will say “De-nied!” and hide the window. Including when the computer tries to, say, shut down.
I’d like to note this isn’t a problem in Windows Vista or above, which ignores the app saying “De-nied!” and
The Solution
Through persistent Googling of the problem (as, once I’d figured out the problem went away after you killed Software Updater, on a hunch I tried searching for variations of e.Cancel shutdown problems) I found what I was looking for.It turns out that during my poking around, somehow I’d missed that FormClosing had an e.CloseReason variable. There are quite a few options to choose from, but the one we’re looking for is CloseReason.WindowsShutDown. To wit:
Private Sub Main_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If Not e.CloseReason = CloseReason.WindowsShutDown Then
e.Cancel = True
Me.Visible = False
End If
End Sub