设置系统时间c#不工作

时间:2014-10-08 13:12:03

标签: c# datetime time set

我正在尝试在Windows上的c#应用程序中设置Windows SystemTime。我已经实现了每个论坛中的示例(包括此处),但它没有响应。 我有一个私有类,有两个方法:GetSystemTime()和SetSystemTime()。 GetSystemTime工作正常,但SetSystemTime没有设置我试图从GetNetworkTime()传递的时间。 我做错了什么?我已经研究过,我不知道这是一个特权问题(我是以管理员身份登录,不应该),也可能是日期格式的问题。

问题是:当SetSystemTime()完成时,我应该看到系统时钟的变化吗?我怎么知道它运行良好?因为我没有看到任何变化。 在这里,我复制了类,以及GetNetworkTime方法,它从NTP服务器获取实际小时数。

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));
    }

2 个答案:

答案 0 :(得分:2)

MSDN说

  

如果函数成功,则返回值为非零。如果功能   失败,返回值为零。要获取扩展的错误信息,   调用GetLastError。

请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/ms724942%28v=vs.85%29.aspx了解整页。

您是否尝试检查返回值,因此最后一次错误?

以下是获取返回值和上一个错误代码的代码示例: (只需替换你自己的&#34; SetSystemTime&#34;电话)

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

不要忘记为GetLastError添加导入:

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

编辑:我刚尝试过,我收到错误&#34; ERROR_INVALID_PARAMETER 87(0x57)参数不正确。&#34;。

所以,按照这个建议,我再次阅读你的代码:

您写道:

   systime.wHour = (ushort)d.Year;

而不是:

   systime.wYear = (ushort)d.Year;

修正了它,然后再没有错误。

答案 1 :(得分:1)

要更改系统时间,您需要具有以下权限:SeSystemTimePrivilege

或者您可以以管理员身份运行您的应用程序。您以管理员身份登录这一事实无法改变,因为它已与UAC相关联。您可以完全禁用UAC,但我不建议这样做。