我正在尝试在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));
}
答案 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,但我不建议这样做。