set system time c# not working

2

I'm trying to set Windows SystemTime in a c# Application on Windows. I've implemented the example that is in every forum (including here) but it's not responding. I have a private class with two methods: GetSystemTime() and SetSystemTime(). GetSystemTime is working fine, but SetSystemTime is not setting the time I'm trying to pass from GetNetworkTime(). I'm doing something wrong? I've researched and I don't know if it's a privilege problem (I'm logged as Administrator, it shouldn't) or maybe a problem with date format.

The thing is: Should I see change in System clock when SetSystemTime() finishes? How I know it's running well? Because I'm not seeing any changes. Here I copy the class, and also GetNetworkTime Method, which get the actual hour from and NTP Server.

public static class SystemTime
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        private extern static void GetSystemTime(ref SYSTEMTIME systime);
        [DllImport("kernel32.dll", SetLastError = true)]
        private extern static uint SetSystemTime(ref SYSTEMTIME systime);

        private struct SYSTEMTIME
        {
            public ushort wYear;
            public ushort wMonth;
            public ushort wDayOfWeek;
            public ushort wDay;
            public ushort wHour;
            public ushort wMinute;
            public ushort wSecond;
            public ushort wMilliseconds;
        }

        private static void GetTime()
        {
            // Call the native GetSystemTime method
            // with the defined structure.
            SYSTEMTIME stime = new SYSTEMTIME();
            GetSystemTime(ref stime);
        }

        public static void SetTime()
        {
            GetTime();
            SYSTEMTIME systime = new SYSTEMTIME();
            try
            {
                DateTime d = Intex.Core.Utils.Common.GetNetworkTime();

                systime.wHour = (ushort)d.Year;
                systime.wMonth = (ushort)d.Month;
                systime.wDayOfWeek = (ushort)d.DayOfWeek;
                systime.wDay = (ushort)d.Day;
                systime.wHour = (ushort)d.Hour;
                systime.wMinute = (ushort)d.Minute;
                systime.wSecond = (ushort)d.Second;
                systime.wMilliseconds = (ushort)d.Millisecond;

                SetSystemTime(ref systime);
                GetTime();
            }
            catch (Exception)
            {
                GetSystemTime(ref systime);
                SetSystemTime(ref systime);
           } 

        }
    }


public static DateTime GetNetworkTime()
    {
        //default Windows time server
        string ntpServer = ConfigurationManager.AppSettings["NTPServer"];

        // NTP message size - 16 bytes of the digest (RFC 2030)
        var ntpData = new byte[48];

        //Setting the Leap Indicator, Version Number and Mode values
        ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)

        var addresses = Dns.GetHostEntry(ntpServer).AddressList;

        //The UDP port number assigned to NTP is 123
        var ipEndPoint = new IPEndPoint(addresses[0], 123);
        //NTP uses UDP
        var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        socket.Connect(ipEndPoint);

        //Stops code hang if NTP is blocked
        socket.ReceiveTimeout = 3000;

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

        //Offset to get to the "Transmit Timestamp" field (time at which the reply 
        //departed the server for the client, in 64-bit timestamp format."
        const byte serverReplyTime = 40;

        //Get the seconds part
        ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);

        //Get the seconds fraction
        ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);

        //Convert From big-endian to little-endian
        intPart = SwapEndianness(intPart);
        fractPart = SwapEndianness(fractPart);

        var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);

        //**UTC** time
        var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);

        return networkDateTime.ToLocalTime();            
    }

    static uint SwapEndianness(ulong x)
    {
        return (uint)(((x & 0x000000ff) << 24) +
                       ((x & 0x0000ff00) << 8) +
                       ((x & 0x00ff0000) >> 8) +
                       ((x & 0xff000000) >> 24));
    }
c#
datetime
time
set
asked on Stack Overflow Oct 8, 2014 by user1545878 • edited Oct 8, 2014 by user1545878

2 Answers

3

The MSDN says

If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError.

See http://msdn.microsoft.com/en-us/library/windows/desktop/ms724942%28v=vs.85%29.aspx for whole page.

Did you try to check the return value and hence, last error ?

Here is a code sample to get return value and last error code : (just replace your own "SetSystemTime" call)

var ret = SetSystemTime(ref systime);
Console.WriteLine("SetSystemTime return : " + ret);
System.Console.WriteLine("Last error : " + GetLastError());

Don't forget to add import for GetLastError :

[DllImport("kernel32.dll")]
static extern uint GetLastError();                

edit : I've just made a try, I get error "ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect.".

So, following this advice, I've read again your code :

You wrote :

   systime.wHour = (ushort)d.Year;

instead of :

   systime.wYear = (ushort)d.Year;

Fixed it, and then, no more error.

answered on Stack Overflow Oct 8, 2014 by AFract • edited Oct 8, 2014 by AFract
1

In order to change the system time you need to have a following privilege: SeSystemTimePrivilege

Or you can run your application as administrator. The fact that you are logged as administrator won't change that because it's linked to the UAC. You can disable the UAC completely but I wouldn't recommend that.

answered on Stack Overflow Nov 28, 2016 by E.T

User contributions licensed under CC BY-SA 3.0