使用C#以编程方式设置时间

在远程计算机上远程设置时间的最佳方法是什么? 该计算机正在运行Windows XP,并通过Web服务调用接收新时间。 目标是使远程计算机与服务器保持同步。 系统被锁定,因此我们的Web服务是唯一的访问权限,因此我无法在每台远程计算机上使用时间服务器。

我会使用Windows内置的互联网时间能力。 您可以在服务器上设置时间服务器 ,让它从第二层时间服务器获取时间,并让所有客户端计算机从中获取时间。

我以前一直在应用设置系统时间之路上。

这是用于设置系统时间的Win32 API调用:

[StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public short wYear; public short wMonth; public short wDayOfWeek; public short wDay; public short wHour; public short wMinute; public short wSecond; public short wMilliseconds; } [DllImport("kernel32.dll", SetLastError=true)] public static extern bool SetSystemTime(ref SYSTEMTIME theDateTime ); 

我不确定如何使安全性得到解决,以便您可以在客户端上执行该function。

您可以在PInvoke上获得有关设置系统时间的更多详细信息。

查询网络机器的系统时间的方法是NetRemoteTOD 。

这是Delphi中的代码(下面发布了一个用法示例)。

由于它依赖于Windows API调用,因此在C#中不应该有太大的不同。

 unit TimeHandler; interface type TTimeHandler = class private FServerName : widestring; public constructor Create(servername : widestring); function RemoteSystemTime : TDateTime; procedure SetLocalSystemTime(settotime : TDateTime); end; implementation uses Windows, SysUtils, Messages; function NetRemoteTOD(ServerName :PWideChar; var buffer :pointer) : integer; stdcall; external 'netapi32.dll'; function NetApiBufferFree(buffer : Pointer) : integer; stdcall; external 'netapi32.dll'; type //See MSDN documentation on the TIME_OF_DAY_INFO structure. PTime_Of_Day_Info = ^TTime_Of_Day_Info; TTime_Of_Day_Info = record ElapsedDate : integer; Milliseconds : integer; Hours : integer; Minutes : integer; Seconds : integer; HundredthsOfSeconds : integer; TimeZone : LongInt; TimeInterval : integer; Day : integer; Month : integer; Year : integer; DayOfWeek : integer; end; constructor TTimeHandler.Create(servername: widestring); begin inherited Create; FServerName := servername; end; function TTimeHandler.RemoteSystemTime: TDateTime; var Buffer : pointer; Rek : PTime_Of_Day_Info; DateOnly, TimeOnly : TDateTime; timezone : integer; begin //if the call is successful... if 0 = NetRemoteTOD(PWideChar(FServerName),Buffer) then begin //store the time of day info in our special buffer structure Rek := PTime_Of_Day_Info(Buffer); //windows time is in GMT, so we adjust for our current time zone if Rek.TimeZone <> -1 then timezone := Rek.TimeZone div 60 else timezone := 0; //decode the date from integers into TDateTimes //assume zero milliseconds try DateOnly := EncodeDate(Rek.Year,Rek.Month,Rek.Day); TimeOnly := EncodeTime(Rek.Hours,Rek.Minutes,Rek.Seconds,0); except on e : exception do raise Exception.Create( 'Date retrieved from server, but it was invalid!' + #13#10 + e.Message ); end; //translate the time into a TDateTime //apply any time zone adjustment and return the result Result := DateOnly + TimeOnly - (timezone / 24); end //if call was successful else begin raise Exception.Create('Time retrieval failed from "'+FServerName+'"'); end; //free the data structure we created NetApiBufferFree(Buffer); end; procedure TTimeHandler.SetLocalSystemTime(settotime: TDateTime); var SystemTime : TSystemTime; begin DateTimeToSystemTime(settotime,SystemTime); SetLocalTime(SystemTime); //tell windows that the time changed PostMessage(HWND_BROADCAST,WM_TIMECHANGE,0,0); end; 

以下是用法示例:

 procedure TfrmMain.SynchLocalTimeWithServer; var tod : TTimeHandler; begin tod := TTimeHandler.Create(cboServerName.Text); try tod.SetLocalSystemTime(tod.RemoteSystemTime); finally FreeAndNil(tod); end; //try-finally end; 

这是我多年来一直使用的例程,用于从我们的SQL Server读取DateTime值(使用文件时间),将其转换为在PC上设置的SYSTEMTIME

这适用于PC和Windows Mobile设备。

它可以在您碰巧调用SQL Server时调用。

 public class TimeTool { private static readonly DateTime NODATE = new DateTime(1900, 1, 1); #if PocketPC [DllImport("coredll.dll")] #else [DllImport("kernel32.dll")] #endif static extern bool SetLocalTime([In] ref SYSTEMTIME lpLocalTime); public struct SYSTEMTIME { public short Year, Month, DayOfWeek, Day, Hour, Minute, Second, Millisecond; ///  /// Convert form System.DateTime ///  /// Creates System Time from this variable public void FromDateTime(DateTime time) { Year = (short)time.Year; Month = (short)time.Month; DayOfWeek = (short)time.DayOfWeek; Day = (short)time.Day; Hour = (short)time.Hour; Minute = (short)time.Minute; Second = (short)time.Second; Millisecond = (short)time.Millisecond; } public DateTime ToDateTime() { return new DateTime(Year, Month, Day, Hour, Minute, Second, Millisecond); } public static DateTime ToDateTime(SYSTEMTIME time) { return time.ToDateTime(); } } // read SQL Time and set time on device public static int SyncWithSqlTime(System.Data.SqlClient.SqlConnection con) { SYSTEMTIME systemTime = new SYSTEMTIME(); DateTime sqlTime = NODATE; string sql = "SELECT GETDATE() AS [CurrentDateTime]"; using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, con)) { try { cmd.Connection.Open(); System.Data.SqlClient.SqlDataReader r = cmd.ExecuteReader(); while (r.Read()) { if (!r.IsDBNull(0)) { sqlTime = (DateTime)r[0]; } } } catch (Exception) { return -1; } } if (sqlTime != NODATE) { systemTime.FromDateTime(sqlTime); // Convert to SYSTEMTIME if (SetLocalTime(ref systemTime)) { //Call Win32 API to set time return 1; } } return 0; } } 

您也可以使用某种组合在批处理文件中执行此操作

 TIME 

设定时间,和

 net time \\server_name 

从服务器检索时间。