2008-10-15 73 views
7

遠程設置遠程計算機上的時間的最佳方法是什麼?該機器正在運行Windows XP,並通過Web服務呼叫接收新時間。目標是讓遠程機器與服務器保持同步。系統被鎖定,以便我們的Web服務是唯一的訪問,所以我不能在每臺遠程機器上使用時間服務器。使用C#以編程方式設置時間

回答

5

我會使用Windows內置的互聯網時間能力。您可以在服務器上設置time server,讓它從第二層時間服務器獲得時間,並讓所有客戶端計算機都能從中獲得時間。

我以前一直在關注應用程序設置系統時間。

8

這是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

+1

+1,順便說一句,我發現這個鏈接有一個完整的源代碼。 http://www.pcreview.co.uk/forums/thread-2085327.php – 2010-06-29 07:16:28

+0

不知道爲什麼,但是這樣在每組之後給了我+2小時的時間。所以設置時間2011.04.23 7:20 ...結果是2011.04.23 9:20。奇怪,但是當我嘗試:2001.03.05 01:55,運作良好。 – 2011-04-21 05:01:30

+0

這是如何在遠程機器上設置時間的? – 2013-10-22 16:58:21

3

查詢網絡機器的系統時間的方法是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; 
0

你也使用

TIME 

某種組合來設置時間可能做到這一點的一個批處理文件,並

net time \\server_name 

檢索從服務器的時間。

1

這是我多年來一直使用的例程來讀取我們的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; 
    } 

}