Установите время программно с помощью C # - PullRequest
7 голосов
/ 15 октября 2008

Каков наилучший способ установить время на удаленной машине удаленно? Машина работает под управлением Windows XP и получает новое время через вызов веб-службы. Цель состоит в том, чтобы синхронизировать удаленные машины с сервером. Система заблокирована, поэтому наш веб-сервис является единственным доступом, поэтому я не могу использовать сервер времени на каждом удаленном компьютере.

Ответы [ 5 ]

8 голосов
/ 15 октября 2008

Это вызов 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 .

5 голосов
/ 15 октября 2008

Я бы использовал встроенные в Windows возможности интернет-времени. Вы можете настроить сервер времени на своем сервере, чтобы он получал время от сервера времени второго уровня, и чтобы все ваши клиентские машины получали время от него.

Раньше я шел по пути установки-настройки системы-времени.

3 голосов
/ 15 октября 2008

Способ запроса системного компьютера о его системном времени: NetRemoteTOD .

Вот код для этого в Delphi (пример использования приведен ниже).

Поскольку он опирается на вызовы API Windows, он не должен быть слишком отличным в 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;
1 голос
/ 02 июля 2012

Вот процедура, которую я использовал годами, чтобы прочитать значение DateTime с нашего сервера SQL Server (используя время файла), преобразовать его в SYSTEMTIME, установленное на ПК.

Это работает для ПК и устройств 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;
  }

}
0 голосов
/ 15 октября 2008

Вы также можете сделать это в командном файле, используя комбинацию

TIME

для установки времени и

net time \\server_name

для получения времени с сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...