2

I'm writing a Windows service using VB.Net and the built-in System.ServiceProcess.ServiceBase class that uses the OnSessionChange function to track when users log in and out. This is so that I can determine how much time each user spends on the computer.

I would like to detect when the system time changes, so that this does not affect the accuracy of the data collected, and it looks like Microsoft has added a message for this purpose: SERVICE_CONTROL_TIMECHANGE, as of Windows 7.

However, the built-in ServiceBase class does not support this message, and doesn't seem to be easily extensible so that I can add full support for this message. Note that I can receive the message (stripped of it's parameter) using this code:

Public Class TimeManager
    Public Sub New()
        InitializeComponent()
        'Modify base class' field...
        EnableTimeChange()
    End Sub
    Private Sub EnableTimeChange()
        Try
            Dim acceptedCommands As Reflection.FieldInfo = Me.GetType().BaseType.GetField("acceptedCommands", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.IgnoreCase)
            If acceptedCommands IsNot Nothing Then
                Dim Value As Integer = acceptedCommands.GetValue(Me)
                Value = Value Or &H200
                acceptedCommands.SetValue(Me, Value)
            Else
                Me.EventLog.WriteEntry("Reflection could not find 'acceptedCommands'!", EventLogEntryType.Warning)
            End If
        Catch ex As Exception
            Me.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Warning)
        End Try
    End Sub
    Protected Overrides Sub OnCustomCommand(command As Integer)
        Select Case command
            Case 16 'SERVICE_CONTROL_TIMECHANGE

                Me.EventLog.WriteEntry("Time changed!",  EventLogEntryType.Information)

        End Select
    End Sub
End Class

I really need that parameter though, because it says what the old time was (before the time change). How should I go about this? Is there a way to do it without re-implementing ServiceBase myself?

camerondm9
  • 1,005
  • 15
  • 22
  • Look here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683241(v=vs.85).aspx and here: https://msdn.microsoft.com/en-us/library/windows/desktop/dd405511(v=vs.85).aspx. It's C++, but it explains what you want to do – Camilo Terevinto Jan 05 '16 at 22:47
  • Yeah, I've been looking at those pages. The `ServiceBase` provides a wrapper around the handler function (first page). I'd like to hook into it so I can handle messages that it doesn't (second page), without having to reimplement everything. – camerondm9 Jan 05 '16 at 22:53
  • Also, take a look at this: http://stackoverflow.com/questions/9725180/c-sharp-event-to-detect-daylight-saving-or-even-manual-time-change. It's a hack, but the OP says that code solved your issue – Camilo Terevinto Jan 05 '16 at 22:54
  • That gets pretty close, but the WM_TIMECHANGE message doesn't say what the old time was. I need that that information too... – camerondm9 Jan 05 '16 at 23:19

0 Answers0