使用 C# 以编程方式设置时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/204936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set time programmatically using C#
提问by Jim Blake
What is the best way to set the time on a remote machine remotely? The machine is running Windows XP and is receiving the new time through a web service call. The goal is to keep the remote machines in synch with the server. The system is locked down so that our web service is the only access, so I cannot use a time server on each remote machine.
在远程机器上远程设置时间的最佳方法是什么?机器运行 Windows XP 并通过 Web 服务调用接收新时间。目标是保持远程机器与服务器同步。系统已锁定,因此我们的 Web 服务是唯一的访问权限,因此我无法在每台远程机器上使用时间服务器。
采纳答案by Joel B Fant
I would use Windows built-in internet time abilities. You can set up a time serveron your server, have it get time from a 2nd-tier timeserver, and have all your client machines get time from it.
我会使用 Windows 内置的互联网时间功能。您可以在您的服务器上设置一个时间服务器,让它从第二层时间服务器获取时间,并让所有客户端机器从中获取时间。
I've been down the application-setting-system-time road before.
我以前一直在应用程序设置系统时间的道路上。
回答by Robert S.
This is the Win32 API call for setting system time:
这是用于设置系统时间的 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 );
I'm not exactly sure how you would get the security worked out such that you could execute that function on the client, though.
不过,我不确定如何解决安全性问题,以便您可以在客户端上执行该功能。
You can get a lot more detail on setting system time at PInvoke.
您可以在PInvoke获得更多关于设置系统时间的详细信息。
回答by JosephStyons
The way to query a network machine for it's system time is NetRemoteTOD.
查询网络机器的系统时间的方法是NetRemoteTOD。
Here's code to do it in Delphi (a usage example is posted below).
这是在 Delphi 中执行此操作的代码(下面发布了一个使用示例)。
Since it relies on Windows API calls, it shouldn't be too different in C#.
由于它依赖于 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;
And here is the usage example:
这是使用示例:
procedure TfrmMain.SynchLocalTimeWithServer;
var
tod : TTimeHandler;
begin
tod := TTimeHandler.Create(cboServerName.Text);
try
tod.SetLocalSystemTime(tod.RemoteSystemTime);
finally
FreeAndNil(tod);
end; //try-finally
end;
回答by JosephStyons
You could also probably do this in a batch file using some combination of
您也可以使用某些组合在批处理文件中执行此操作
TIME
to set the time, and
设置时间,以及
net time \server_name
to retrieve the time from a server.
从服务器检索时间。
回答by jp2code
Here's the routine I have been using for years to read the DateTime
value off our our SQL Server (using file time), convert it to a SYSTEMTIME
that is set on the PC.
这是我多年来一直使用的例程,DateTime
从我们的 SQL Server读取值(使用文件时间),将其转换SYSTEMTIME
为在 PC 上设置的值。
This works for PCs and Windows Mobile devices.
这适用于 PC 和 Windows Mobile 设备。
It can be called anytime you happen to be calling your SQL Server.
它可以在您调用 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;
}
}