C#

2008-10-15 18 views
7

ile programlı bir şekilde zaman ayarlayın Uzak bir makinede saati uzaktan ayarlamanın en iyi yolu nedir? Makine Windows XP'yi çalıştırıyor ve yeni süreyi bir web servis çağrısı aracılığıyla alıyor. Amaç uzak makinelerin sunucuyla senkronize olmasını sağlamaktır. Sistem, web servisimizin tek erişim olduğu şekilde kilitlenmiştir, bu yüzden her uzak makinede bir zaman sunucusu kullanamıyorum.C#

[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); 

Sana güvenliğini alacağı tam olarak nasıl emin değilim gerçi, istemci üzerinde bu işlevi gerçekleştirmek olabilir, öyle ki çalıştı:

cevap

5

Windows yerleşik internet saati yeteneklerini kullanırdım. Sunucunuza bir time server kurabilir, 2. kademe zamanlayıcısından zaman alabilir ve tüm müşteri makinelerinizden zaman kazanabilirsiniz.

önce uygulamaya ayar sistemi zamanlı yolda oldum.

+0

Bunu destekleyeceğim. Zaman protokolü sağdaki popodaki bir ağrıdır. Mümkünse yerleşik servisi kullanın. –

8

Bu sistem saatini ayarlamak için Win32 API çağrıdır.

Sen PInvoke de sistem saatini ayarlama konusunda çok daha fazla detay alabilirsiniz.

+1

+1, BTW, Bu bağlantıyı eksiksiz bir kaynak kodu ile buldum. http://www.pcreview.co.uk/forums/thread-2085327.php –

+0

Neden olduğu hakkında hiçbir fikrim yok, ama bu her setten sonra +2 saat verdi. Bu nedenle 2011.04.23 7:20 ayar zamanı, 2011.04.23 9:20 sonuçlandı. Garip, ama denediğimde: 2001.03.05 01:55, iyi çalıştı. –

+0

Bu, uzak bir makinede zamanı nasıl ayarlıyor? –

3

sistem zamanı için bir ağ makinesini sorgulamak için bir yol NetRemoteTOD olduğunu.

İşte Delphi (bir kullanım örneği aşağıda nakledilir) bunu yapmak için kod. Windows API çağrıları temel aldığından

, bu C# çok farklı olmamalıdır. Burada

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; 

Ve

kullanım örneği:

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

Bunun neden reddedildiğini merak ediyorum. – JosephStyons

+1

Sanırım C# etiketi ile soru soruldu, ancak Delphi/Pascal örnekleriyle yanıtladığınız için bunun düşürülmüş olduğunu tahmin ediyorum – evilone

0

Ayrıca muhtemelen zamanını ayarlamak için

TIME 

bazı kombinasyonunu kullanan bir toplu dosyasında bu yapabileceğini ve

net time \\server_name 

almak için bir sunucudan zaman.

1

SQL Server'ımızdan (dosya zamanını kullanarak) DateTime değerini okumak için yıllardır kullandığım yordam, PC'de ayarlanan SYSTEMTIME'a dönüştürün.

Bu, PC'ler ve Windows Mobile aygıtları için çalışır.

SQL Server'ınızı çağırdığınızda her zaman aranabilir.

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; 
    } 

}