Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
OnShutdown event in a Windows Service
Message
From
28/03/2014 09:08:25
 
 
General information
Forum:
ASP.NET
Category:
Other
Environment versions
Environment:
VB 9.0
OS:
Windows 7
Network:
Windows 2003 Server
Database:
MS SQL Server
Application:
Web
Miscellaneous
Thread ID:
01597504
Message ID:
01597543
Views:
38
>.NET has the SystemEvents.SessionEnding event : http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending(v=vs.110).aspx
>
>It uses the message pump so it's not quite so simple to use in a windows service. MS suggest either using the local system account and setting 'Allow service to interact with desktop' or using a hidden form. See second example here : http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents(v=vs.110).aspx

Thanks, I have taken a look at that and came up with this:
Imports System.ServiceProcess
Imports System.Threading
Imports System.Windows.Forms
Imports Microsoft.Win32

Public Class WindowsService
    Inherits ServiceBase

    Public Sub New()
        CanStop = True
        CanShutdown = True
        CanPauseAndContinue = False
    End Sub

    Protected Overrides Sub OnStart(ByVal toArgs As String())
        Dim loThread As New Thread(AddressOf RunMessagePump)

        loThread.Start()
    End Sub

    Sub RunMessagePump()
        EventLog.WriteEntry("SimpleService.MessagePump", "Starting SimpleService Message Pump")
        Application.Run(New HiddenForm())
    End Sub

End Class

Partial Class HiddenForm
    Inherits Form

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub HiddenForm_Load(ByVal sender As Object, ByVal e As EventArgs)
        AddHandler SystemEvents.TimeChanged, AddressOf SystemEvents_TimeChanged
        AddHandler SystemEvents.UserPreferenceChanged, AddressOf SystemEvents_UPCChanged
    End Sub

    Private Sub HiddenForm_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
        RemoveHandler SystemEvents.TimeChanged, New EventHandler(AddressOf SystemEvents_TimeChanged)
        RemoveHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf SystemEvents_UPCChanged)
    End Sub

    Private Sub SystemEvents_TimeChanged(ByVal sender As Object, ByVal e As EventArgs)
        EventLog.WriteEntry("SimpleService.TimeChanged", "Time changed; it is now " & DateTime.Now.ToLongTimeString())
    End Sub

    Private Sub SystemEvents_UPCChanged(ByVal sender As Object, ByVal e As UserPreferenceChangedEventArgs)
        EventLog.WriteEntry("SimpleService.UserPreferenceChanged", e.Category.ToString())
    End Sub

    Private Shared WM_QUERYENDSESSION As Integer = &H11
    Private Shared lSystemShutdown As Boolean = False

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

        ' If this is a logoff, shutdown or reboot
        If m.Msg = WM_QUERYENDSESSION Then
            MessageBox.Show("queryendsession: this is a logoff, shutdown, or reboot")
            lSystemShutdown = True
        End If

        ' If this is WM_QUERYENDSESSION, the closing event should be raised in the base WndProc
        MyBase.WndProc(m)

    End Sub

    Private Sub Form1_Closing(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

        ' Force Closing to recognize that we already have a shutdown for testing purposes
        lSystemShutdown = True

        ' If this is a shutdown
        If lSystemShutdown Then

            ' Reset the variable because the user might cancel the shutdown
            lSystemShutdown = False

            If MessageBox.Show("My application", "Do you want to save your work before logging off?", MessageBoxButtons.YesNo) = _
             System.Windows.Forms.DialogResult.Yes Then
                e.Cancel = True
            Else
                e.Cancel = False
            End If

        End If

    End Sub

End Class

Partial Class HiddenForm

    Private components As System.ComponentModel.IContainer = Nothing

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)

        If disposing AndAlso Not (components Is Nothing) Then
            components.Dispose()
        End If

        MyBase.Dispose(disposing)
    End Sub

    Private Sub InitializeComponent()
        SuspendLayout()
        'AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
        AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        'ClientSize = New System.Drawing.Size(0, 0)
        FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
        Name = "HiddenForm"
        Text = "HiddenForm"
        WindowState = System.Windows.Forms.FormWindowState.Minimized
        AddHandler Me.Load, AddressOf Me.HiddenForm_Load
        AddHandler Me.FormClosing, AddressOf Me.HiddenForm_FormClosing
        ResumeLayout(False)
    End Sub

End Class
I did not include everything. I only included what was related to this shutdown event.

So, I started the Windows Service. And, issue a restart. It went straight through the restart without even asking me the question. In the closing event, I forced the lSystemShutdown to be True. So, I wanted to simulate that message. The reboot proceeded without any message.

There has to be something I am missing. I also do not know why there are two Partial Class HiddenForm. Would there had been a way to consolidate everything into one single HiddenForm class?

In overall, there is an OnShutDown event at the Windows Service level. I do not understand why it is so complicated to get a hook to this event.
Michel Fournier
Level Extreme Inc.
Designer, architect, owner of the Level Extreme Platform
Subscribe to the site at https://www.levelextreme.com/Home/DataEntry?Activator=55&NoStore=303
Subscription benefits https://www.levelextreme.com/Home/ViewPage?Activator=7&ID=52
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform