How do I get the Server time or current time of day and switch to the system via code?

Asked

Viewed 2,942 times

0

I need to update an O.S system with the time of another micro, if this other micro would be a server. I would like to do this via code.

Another method that would also help would be to take the right time of day and compare it with the computer that will be running the program.

  • Do you really need to change the time of the OS? It might be better if you always use the date and time of the database, the OS you may not be allowed to change, and if it is an enterprise network Windows may already be set up to synchronize the time with the server.

2 answers

1

class Program
{
    //necessário privilégio administrador
    [DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)]
    public extern static bool Win32SetSystemTime(ref SystemTime sysTime);

    [DllImport("kernel32.dll", EntryPoint = "GetSystemTime", SetLastError = true)]
    public extern static void Win32GetSystemTime(ref SystemTime sysTime);

    public struct SystemTime
    {
        public ushort Year;
        public ushort Month;
        public ushort DayOfWeek;
        public ushort Day;
        public ushort Hour;
        public ushort Minute;
        public ushort Second;
        public ushort Millisecond;
    }

    private static void Main()
    {
        //servidor intranet "user-PC" (local)
        //a.ntp.br (internet) 
        //var localDateTime = PegarDtHoraRedeLocal("user-PC");
        var horaAtual = PegarDtHoraAtualizada("a.ntp.br");

        //AJUSTA HORA BASEADO NO FUSO HORARIO DO COMPUTADOR LOCAL
        SetTime(horaAtual.ToUniversalTime());
        Console.ReadKey();
    }

    public static DateTime PegarDtHoraAtualizada(string ntpServer)
    {
        var ntpData = new byte[48];
        ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)

        //somente IPV4
        var addresses = Dns.GetHostEntry(ntpServer).AddressList.First(a => a.AddressFamily == AddressFamily.InterNetwork);

        var ipEndPoint = new IPEndPoint(addresses, 123);
        var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        socket.ReceiveTimeout = 5000; //5 segundos timeout
        socket.Connect(ipEndPoint);
        socket.Send(ntpData);
        socket.Receive(ntpData);
        socket.Close();

        ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | ntpData[43];
        ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | ntpData[47];

        var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
        var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long) milliseconds).ToLocalTime();

        //ajustando para hora brasil teste ajuste independente do fuso horario
        //networkDateTime = DateTime.ParseExact(networkDateTime.ToString(), "dd/M/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
        return networkDateTime;
    }

    private static void SetTime(DateTime dataHoraAtualizada)
    {
        // Prepare native method with the defined structure.
        var st = new SystemTime
        {
            Year = (ushort) (dataHoraAtualizada.Year),
            Month = (ushort) (dataHoraAtualizada.Month),
            Hour = (ushort) (dataHoraAtualizada.Hour),
            Day = (ushort) (dataHoraAtualizada.Day),
            Minute = (ushort) (dataHoraAtualizada.Minute),
            Second = (ushort) (dataHoraAtualizada.Second)
        };

        // Set the system date time.
        var resp = Win32SetSystemTime(ref st);
        Debug.Print(resp.ToString());
    }
}

I need to update an O.S system with the time of another micro, in case this one another micro would be a server. I would like to do this via code.

var localDateTime = PegarDtHoraRedeLocal("user-PC"); //user-PC: nome servidor sua rede local
//AJUSTA HORA BASEADO NO FUSO HORARIO DO COMPUTADOR LOCAL
SetTime(horaAtual.ToUniversalTime());

OBS:

  1. The Windows Time service (W32time) acts as the server responsible for providing the time, so it must be started;
  2. I have tested computer locally with WINXP SP3 and WIN7 (Professional). XPSP3 does not need additional configuration;
  3. To configure WIN7 (as NTP server - Network Time Protocol) follow the steps below:

    3.1 Stop the service (W32time - Windows Time), can be by the service manager or by command promptnet stop w32time

    3.2 Open the windows registry regedit.exe

    3.3 Navigate to the key HKEY_LOCAL_MACHINE SYSTEM Currentcontrolset Services W32time Config Announceflags changes the value of 10 for 5

    3.4 Navigate to the key HKEY_LOCAL_MACHINE SYSTEM Currentcontrolset services W32time Timeproviders Ntpserver
    change the value to 1

    3.5 Start the service (W32time - Windows time) net start w32time

    3.6 To verify that the NTP server is configured correctly, type in command prompt w32tm /query /Configuration and see if image appears below is configured
    inserir a descrição da imagem aqui

Another method that would also help would be to take the right time of day and compare with the computer that will be running the program.

Here you take the right time of day and can compare to your server @Felipe-walleg

var horaAtual = PegarDtHoraAtualizada("a.ntp.br"); //Hora atualizada pela internet    
//AJUSTA HORA BASEADO NO FUSO HORARIO DO COMPUTADOR LOCAL
SetTime(horaAtual.ToUniversalTime());



Sources:
https://msdn.microsoft.com/en-us/library/ms172517(v=vs.90). aspx https://stackoverflow.com/questions/1193955/how-to-query-an-ntp-server-using-c https://social.technet.microsoft.com/Forums/windowsserver/en-US/ffb1df0b-7c6e-4b2d-8fdf-b4ca0c014266/configuring-windows-7-as-an-ntp-server?forum=winserverPN

0


Code in VB.NET Source: https://stackoverflow.com/questions/1193955/how-to-query-an-ntp-server-using-c/12150289#12150289

 Public Shared Function GetNetworkTime() As DateTime
        'Servidor nacional para melhor latência
        Const ntpServer As String = "a.ntp.br"

        ' Tamanho da mensagem NTP - 16 bytes (RFC 2030)
        Dim ntpData = New Byte(47) {}

        'Indicador de Leap (ver RFC), Versão e Modo
        ntpData(0) = &H1B
        'LI = 0 (sem warnings), VN = 3 (IPv4 apenas), Mode = 3 (modo cliente)
        Dim addresses = Dns.GetHostEntry(ntpServer).AddressList

        '123 é a porta padrão do NTP
        Dim ipEndPoint = New IPEndPoint(addresses(0), 123)
        'NTP usa UDP
        Dim socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)

        socket.Connect(ipEndPoint)

        'Caso NTP esteja bloqueado, ao menos nao trava o app
        socket.ReceiveTimeout = 3000

        socket.Send(ntpData)
        socket.Receive(ntpData)
        socket.Close()

        'Offset para chegar no campo "Transmit Timestamp" (que é
        'o do momento da saída do servidor, em formato 64-bit timestamp
        Const serverReplyTime As Byte = 40

        'Pegando os segundos
        Dim intPart As ULong = BitConverter.ToUInt32(ntpData, serverReplyTime)

        'e a fração de segundos
        Dim fractPart As ULong = BitConverter.ToUInt32(ntpData, serverReplyTime + 4)

        'Passando de big-endian pra little-endian
        intPart = SwapEndianness(intPart)
        fractPart = SwapEndianness(fractPart)

        Dim milliseconds = (intPart * 1000) + ((fractPart * 1000) / &H100000000L)

        'Tempo em **UTC**
        Dim networkDateTime = (New DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds(CLng(milliseconds))

        Return networkDateTime.ToLocalTime()
    End Function

    ' stackoverflow.com/a/3294698/162671
    Private Shared Function SwapEndianness(x As ULong) As UInteger
        Return CUInt(((x And &HFF) << 24) + ((x And &HFF00) << 8) + ((x And &HFF0000) >> 8) + ((x And &HFF000000UI) >> 24))
    End Function

Browser other questions tagged

You are not signed in. Login or sign up in order to post.