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 ClassI did not include everything. I only included what was related to this shutdown event.