문제
원격 기계에서 원격으로 시간을 설정하는 가장 좋은 방법은 무엇입니까? 머신은 Windows XP를 실행 중이며 웹 서비스 호출을 통해 새로운 시간을 받고 있습니다. 목표는 원격 기계를 서버와 동기화하는 것입니다. 웹 서비스가 유일한 액세스가되도록 시스템이 잠겨 있으므로 각 원격 시스템에서 시간 서버를 사용할 수 없습니다.
해결책
Windows 내장 인터넷 시간 능력을 사용합니다. 당신은 설정할 수 있습니다 시간 서버 서버에서 2 차 타임 서버에서 시간을 얻고 모든 클라이언트 머신이 시간을 보내도록하십시오.
나는 이전에 신청서-시스템 시간 도로를 내려 갔다.
다른 팁
시스템 시간 설정을위한 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 );
그래도 고객에게 해당 기능을 실행할 수 있도록 보안을 어떻게 해결할 것인지 잘 모르겠습니다.
시스템 시간 설정에 대한 자세한 내용을 얻을 수 있습니다. 핀 보크.
시스템 시간을 위해 네트워크 머신을 쿼리하는 방법은 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;
다음은 몇 년 동안 사용해 온 루틴입니다. DateTime
당사의 SQL Server (파일 시간 사용)에서 가치를 부여하여 SYSTEMTIME
그것은 PC에 설정됩니다.
이것은 PC 및 Windows 모바일 장치에서 작동합니다.
SQL 서버에 전화 할 때 언제든지 호출 할 수 있습니다.
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;
}
}
아마도 일부 조합을 사용하여 배치 파일로 이것을 할 수도 있습니다.
TIME
시간을 설정하고
net time \\server_name
서버에서 시간을 검색합니다.