Question

Quel est le meilleur moyen de régler l'heure sur un ordinateur distant à distance? La machine exécute Windows XP et reçoit la nouvelle heure via un appel de service Web. L'objectif est de maintenir les machines distantes synchronisées avec le serveur. Le système est verrouillé de sorte que notre service Web constitue le seul accès. Par conséquent, je ne peux pas utiliser de serveur de temps sur chaque ordinateur distant.

Était-ce utile?

La solution

J'utiliserais les capacités de temps Internet intégrées de Windows. Vous pouvez configurer un serveur de temps sur votre serveur, pour qu'il obtienne l'heure d'un deuxième niveau. serveur de temps, et que tous vos ordinateurs clients en bénéficient.

Je suis déjà passé par la voie du paramétrage des applications et du temps système.

Autres conseils

Ceci est l'appel de l'API Win32 pour la définition de l'heure système:

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

Je ne sais pas exactement comment vous obtiendrez la sécurité pour pouvoir exécuter cette fonction sur le client.

Vous pouvez obtenir beaucoup plus de détails sur la définition de l'heure système à l'adresse PInvoke .

Pour interroger une machine réseau sur son heure système, procédez comme suit: NetRemoteTOD .

Voici le code pour le faire dans Delphi (un exemple d'utilisation est affiché ci-dessous).

Puisqu'il s'appuie sur les appels de l'API Windows, il ne devrait pas être trop différent en 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;

Et voici l'exemple d'utilisation:

procedure TfrmMain.SynchLocalTimeWithServer;
var
  tod : TTimeHandler;
begin
  tod := TTimeHandler.Create(cboServerName.Text);
  try
    tod.SetLocalSystemTime(tod.RemoteSystemTime);
  finally
    FreeAndNil(tod);
  end;  //try-finally
end;

Voici la routine que j'utilise depuis des années pour lire la valeur DateTime de notre serveur SQL Server (en utilisant la durée du fichier), pour la convertir en un SYSTEMTIME défini. sur le PC.

Ceci fonctionne pour les PC et les appareils Windows Mobile.

Il peut être appelé à tout moment lorsque vous appelez votre serveur 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;
  }

}

Vous pouvez aussi probablement le faire dans un fichier de commandes en utilisant une combinaison de

TIME

pour régler l'heure et

net time \\server_name

pour récupérer l'heure sur un serveur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top