使用C#以编程方式设置时间
本文关键字:设置 时间 方式 编程 使用 | 更新日期: 2023-09-27 17:47:46
在远程机器上远程设置时间的最佳方式是什么?该机器正在运行Windows XP,并通过web服务调用接收新时间。目标是使远程计算机与服务器保持同步。系统被锁定,所以我们的网络服务是唯一的访问权限,所以我不能在每台远程机器上使用时间服务器。
这是用于设置系统时间的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 );
不过,我不太确定你将如何计算安全性,以便在客户端上执行该功能。
您可以在PInvoke中获得更多关于设置系统时间的详细信息。
我会使用Windows内置的互联网时间功能。您可以在服务器上设置一个时间服务器,让它从第二层时间服务器获取时间,并让所有客户端机器从中获取时间。
我以前一直走应用程序设置系统的道路。
查询网络机器系统时间的方法是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;
您也可以使用的某些组合在批处理文件中执行此操作
TIME
设置时间,以及
net time ''server_name
从服务器检索时间。
这是我多年来一直使用的例程,用于从我们的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;
/// <summary>
/// Convert form System.DateTime
/// </summary>
/// <param name="time">Creates System Time from this variable</param>
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;
}
}