locked
reading a date from registry in REG_BINARY format and converting to a readable datetime RRS feed

  • Question

  • Hi

    I am trying to obtain a datetime from registry

    I can read all other values I need okay, but am struggling on how to get a date from a REG_BINARY

    Spent a while googling but not yet got a working answer

    Any ideas please?


    Darren Rose

    Tuesday, November 17, 2020 8:55 PM

Answers

  • You don't need to go to the registry for this information.  It can be returned by the Network List Manager interfaces.  For example, after adding a reference to the COM type library and importing the NETWORKLIST namespace (error checking omitted) -

    Imports NETWORKLIST
    Imports System.Runtime.InteropServices
    
    Module Module1
        <StructLayout(LayoutKind.Explicit)>
        Public Structure LONG_INTEGER
            <FieldOffset(0)>
            Public LowPart As UInteger
            <FieldOffset(4)>
            Public HighPart As Integer
            <FieldOffset(0)>
            Public QuadPart As Long
        End Structure
    
    
        Sub Main()
            Dim nlm As INetworkListManager = New NetworkListManager()
            Dim nEnum As IEnumNetworks = nlm.GetNetworks(NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_ALL)
            For Each net As INetwork In nEnum
                Dim ftCreated, ftConnected As LONG_INTEGER
                Dim strName As String = net.GetName()
                net.GetTimeCreatedAndConnected(ftCreated.LowPart, ftCreated.HighPart, ftConnected.LowPart, ftConnected.HighPart)
                Dim dtCreated As DateTime = New DateTime(ftCreated.QuadPart)
                Dim dtConnected As DateTime = New DateTime(ftConnected.QuadPart)
                'FILETIME returned by INetwork interface based on ticks since 1/1/1601 but DateTime constructor based on 1/1/0001 start
                'Add 1600 years to compensate
                Console.WriteLine("Network name is {0}, created {1}, connected {2}",
                                  strName,
                                  dtCreated.AddYears(1600).ToString(),
                                  dtConnected.AddYears(1600).ToString())
            Next
        End Sub
    
    End Module
    

    • Marked as answer by wingers Wednesday, November 18, 2020 1:12 PM
    Wednesday, November 18, 2020 11:36 AM
  • Hi wingers,

    I make a test based on your description, and the following code works for me.

           Using key As RegistryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles\...")
                If key IsNot Nothing Then
                    Dim value As Object = key.GetValue("DateCreated")
                    If value IsNot Nothing Then
    
                        Dim binary As Byte() = CType(value, Byte())
                        If binary Is Nothing OrElse binary.Length <> 16 Then
                            Throw New ArgumentException()
                        End If
    
                        Dim time As DateTime = New DateTime(binary(0) + binary(1) * 256, binary(2), binary(6), binary(8), binary(10), 0)
                    End If
                End If
            End Using

    Result of my test.

    Hope it can help you.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by wingers Wednesday, November 18, 2020 1:12 PM
    Wednesday, November 18, 2020 6:14 AM

All replies

  • Hi

    Try this - no promises though 😊

    Option Strict On
    Option Explicit On
    Public Class Form1
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
        Dim bytes() As Byte = {&H44, &HA5, &HF, &H47, &HC9, &H2C, &HC6, &H1}
    
        Dim dt As Date = GetDateTime(bytes)
      End Sub
    
    
      Public Function GetDateTime(ByVal bytes As Byte()) As DateTime
        Return DateTime.FromFileTime((((((((CLng(bytes(7)) * 256 + CLng(bytes(6))) * 256 + CLng(bytes(5))) * 256 + CLng(bytes(4))) * 256 + CLng(bytes(3))) * 256 + CLng(bytes(2))) * 256 + CLng(bytes(1))) * 256 + CLng(bytes(0))))
      End Function
    End Class


    Regards Les, Livingston, Scotland

    Tuesday, November 17, 2020 10:04 PM
  • Hi Les

    That certainly gets me a date, but not one i would expect

    If it helps it is the DateCreated and DateLastConnected from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles\ I am trying to get


    Darren Rose

    Tuesday, November 17, 2020 10:10 PM
  • Hi

    Please show the byte sequence you are using from the registry to get the DateTime from and, the expected DateTime


    Regards Les, Livingston, Scotland

    Tuesday, November 17, 2020 10:13 PM
  • e4 07 0b 00 05 00 0d 00 00 00 37 00 29 00 e1 00

    Would expect it to be giving a date no more than a week / 10 days old


    Darren Rose

    Tuesday, November 17, 2020 10:16 PM
  • Hi

    Sorry, but I have just had to Repair my Visual Studio as I was getting all sorts of strange things happening (the worsy being a compile failure with no error listed.)

    Now I will need to redo my settings as the saved version seems to be completely different to what I KNOW they were when I saved them.

    I will shut down for the night - I'm pi**** of at the moment with this.

    Maybe someone else will offer something.


    Regards Les, Livingston, Scotland

    Tuesday, November 17, 2020 11:08 PM
  • e4 07 0b 00 05 00 0d 00 00 00 37 00 29 00 e1 00

    should be:

    13 November, 2020 00:55:41.225


    Seems to be a SYSTEMTIME structure, which is 8 two-byte words in little endian order.

    The two-byte words represent year, month, day of week, day, hour, minutes, seconds, milliseconds.
    So:
    e4 07  = year = 2020
    0b 00  = month = 11
    05 00  = day of week = 5
    0d 00 = day = 13
    and so on.


    Tuesday, November 17, 2020 11:11 PM
  • Hi

    Sorry, but I have just had to Repair my Visual Studio as I was getting all sorts of strange things happening (the worsy being a compile failure with no error listed.)

    Now I will need to redo my settings as the saved version seems to be completely different to what I KNOW they were when I saved them.

    I will shut down for the night - I'm pi**** of at the moment with this.

    Maybe someone else will offer something.


    Regards Les, Livingston, Scotland

    Must be the latest update to VS then as I have had strange issues all day, keeps telling me an error occurred and have to restart it

    Darren Rose

    Tuesday, November 17, 2020 11:22 PM
  • Hi wingers,

    I make a test based on your description, and the following code works for me.

           Using key As RegistryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles\...")
                If key IsNot Nothing Then
                    Dim value As Object = key.GetValue("DateCreated")
                    If value IsNot Nothing Then
    
                        Dim binary As Byte() = CType(value, Byte())
                        If binary Is Nothing OrElse binary.Length <> 16 Then
                            Throw New ArgumentException()
                        End If
    
                        Dim time As DateTime = New DateTime(binary(0) + binary(1) * 256, binary(2), binary(6), binary(8), binary(10), 0)
                    End If
                End If
            End Using

    Result of my test.

    Hope it can help you.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by wingers Wednesday, November 18, 2020 1:12 PM
    Wednesday, November 18, 2020 6:14 AM
  • You don't need to go to the registry for this information.  It can be returned by the Network List Manager interfaces.  For example, after adding a reference to the COM type library and importing the NETWORKLIST namespace (error checking omitted) -

    Imports NETWORKLIST
    Imports System.Runtime.InteropServices
    
    Module Module1
        <StructLayout(LayoutKind.Explicit)>
        Public Structure LONG_INTEGER
            <FieldOffset(0)>
            Public LowPart As UInteger
            <FieldOffset(4)>
            Public HighPart As Integer
            <FieldOffset(0)>
            Public QuadPart As Long
        End Structure
    
    
        Sub Main()
            Dim nlm As INetworkListManager = New NetworkListManager()
            Dim nEnum As IEnumNetworks = nlm.GetNetworks(NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_ALL)
            For Each net As INetwork In nEnum
                Dim ftCreated, ftConnected As LONG_INTEGER
                Dim strName As String = net.GetName()
                net.GetTimeCreatedAndConnected(ftCreated.LowPart, ftCreated.HighPart, ftConnected.LowPart, ftConnected.HighPart)
                Dim dtCreated As DateTime = New DateTime(ftCreated.QuadPart)
                Dim dtConnected As DateTime = New DateTime(ftConnected.QuadPart)
                'FILETIME returned by INetwork interface based on ticks since 1/1/1601 but DateTime constructor based on 1/1/0001 start
                'Add 1600 years to compensate
                Console.WriteLine("Network name is {0}, created {1}, connected {2}",
                                  strName,
                                  dtCreated.AddYears(1600).ToString(),
                                  dtConnected.AddYears(1600).ToString())
            Next
        End Sub
    
    End Module
    

    • Marked as answer by wingers Wednesday, November 18, 2020 1:12 PM
    Wednesday, November 18, 2020 11:36 AM
  • @RLWA32 - thank you - didn't realise I could do it like that - very useful

    @Xingyu Zhao - thank you - I can confirm that does work - I had found that similar solution this morning and was trying it when I got your response.  Original version in C# was here - https://social.msdn.microsoft.com/Forums/vstudio/en-US/382c06b1-a660-47da-a6e6-a7b27404581a/regbinary-value-from-registry-to-date-format-conversion?forum=csharpgeneral


    Darren Rose

    Wednesday, November 18, 2020 1:12 PM