Announcement

Collapse
No announcement yet.

Zeit vom Netzwerk holen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Zeit vom Netzwerk holen

    Hallo,<br>
    <br>
    wie kann man (einfach!) die Zeit vom Netzwerk-Server ermitteln. Ich dachte an einen "unsichtbaren" Aufruf von NET TIME, z.B. über ShellExecute. Leider weiß ich nicht, wie man damit einen unsichtbaren Aufruf hinbekommt und wie man auf die Ausgabe von "NET" im Programm zugreifen kann.
    <br>
    Kann mir hir jemand weiterhelfen?<br>
    <br>
    Andreas Richter

  • #2
    Hallo,

    die folgende Unit demonstriert, wie man die Zeit von einem Server holen kann.

    Aufruf:
    <pre>
    procedure TForm1.ButtonServerTimeClick(Sender: TObject);
    var
    ServerUTC: TDateTime;
    sServerName : String;
    begin
    sServerName := StaticTextSelServer.Caption;
    Screen.Cursor := crHourGlass;
    ButtonServerTime.Enabled := false;
    try
    ServerUTC := ServerTime(sServerName);
    StaticTextLocal.Caption := DateTimeToStr(Now);
    StaticTextLocalTZ.Caption := DateTimeToStr(ServerUTC - GetLocalTimeZoneOffSet);
    StaticTextServer.Caption := DateTimeToStr(ServerUTC);
    StaticTextServerTZ.Caption := DateTimeToStr(ServerUTC -
    ServerTimeZoneOffset(sServerName));
    finally
    ButtonServerTime.Enabled := true;
    Screen.Cursor := crDefault;
    end;
    end;
    </pre>
    Implementierung der Funktion ServerTime:
    <pre>
    unit SrvTime;

    interface

    uses
    Windows, SysUtils;

    function ServerTime(ServerName: string): TDateTime;
    function GetLocalTimeZoneOffSet: TDateTime;
    function ServerTimeZoneOffset(ServerName: string): TDateTime;

    implementation

    type
    ENetTODError = Exception;

    PTIMEOFDAYINFO = ^TTimeofDayInfo;
    TTimeofDayInfo = record
    tod_Elapsedt: DWORD; // Seconds since 1-jan-1970 00:00:00
    tod_MSecs: DWORD;
    tod_Hours: DWORD;
    tod_Mins: DWORD;
    tod_Secs: DWORD;
    tod_Hunds: DWORD;
    tod_TimeZone: Integer; // Minutes from GMT [ -1 = undefined ]
    tod_TInterval: DWORD;
    tod_Day: DWord;
    tod_Month: DWORD;
    tod_Year: DWORD;
    tod_WeekDay: DWORD;
    end;

    NET_API_STATUS = Integer;

    const
    NERR_Success = 0;
    MINUTESPERDAY = 1440;

    TIME_ZONE_ID_UNKNOWN = 0;
    TIME_ZONE_ID_STANDARD = 1;
    TIME_ZONE_ID_DAYLIGHT = 2;

    function GetLocalTimeZoneOffSet: TDateTime;
    var
    TZInfo: TTimeZoneInformation;
    begin
    case GetTimeZoneInformation(TZInfo) of
    TIME_ZONE_ID_UNKNOWN:
    Result := TZInfo.bias / MINUTESPERDAY;
    TIME_ZONE_ID_STANDARD:
    Result := (TZInfo.bias + TZInfo.standardbias) / MINUTESPERDAY;
    TIME_ZONE_ID_DAYLIGHT:
    Result := (TZInfo.bias + TZInfo.daylightbias) / MINUTESPERDAY;
    else
    // TIME_ZONE_ID_INVALID
    Result := TZInfo.bias / MINUTESPERDAY;
    end;
    end;

    procedure NetCheck(ErrCode: NET_API_STATUS);
    begin
    if ErrCode <> NERR_Success then
    begin
    case ErrCode of
    ERROR_ACCESS_DENIED:
    raise ENetTODError.Create('Zugriff wird verweigert!');
    ERROR_INVALID_OWNER:
    raise ENetTODError.Create('Objektbesitzer unerreichbar!');
    ERROR_INSUFFICIENT_BUFFER:
    raise ENetTODError.Create('Datenpuffer ist zu kein!');
    else
    raise Exception.Create('Error Code: ' + IntToStr(ErrCode) + #13 +
    SysErrorMessage(ErrCode));
    end;
    end;
    end;

    procedure GetTOD(TimeServer: String; var TOD: TTimeofDayInfo);
    resourcestring
    cLERROR = 'LoadLibrary-Fehler: ';
    const
    NTlib = 'NETAPI32.DLL';
    Win95lib = 'RADMIN32.DLL';
    var
    PresentUTC, Tzo: TDateTime;
    ErrMode: Word;
    nYear, nMonth, nDay, nHours, nMins, nSecs, nMsecs: Word;
    wsSystem: array[1..80] of WideChar;
    LibHandle: THandle;
    pTOD: PTIMEOFDAYINFO;
    NTNetRemoteTODA: function(server: PChar;
    var pTOD: PTimeofDayInfo): NET_API_STATUS; stdcall;
    NTNetRemoteTOD: function(server: PWideChar;
    var pTOD: PTimeofDayInfo): NET_API_STATUS; stdcall;
    NTNetApiBufferFree: function(lpBuffer: Pointer): NET_API_STATUS; stdcall;
    IsWinNT : Boolean;
    szComputerName : array[0..99] of Char;
    dwSIZE : DWord;
    begin
    LibHandle := 0;
    FillChar(TOD, SizeOf(TOD), 0);
    // eigener oder fremder Rechner ?
    GetComputerName(@szComputerName, dwSIZE);
    if Uppercase(TimeServer) = '\\' + szComputerName then
    // eigener Rechner
    with TOD do
    begin
    Tzo := GetLocalTimeZoneOffSet;
    tod_TimeZone := Round(Tzo * MINUTESPERDAY);
    PresentUTC := Now + Tzo;
    DecodeDate(PresentUTC, nYear, nMonth, nDay);
    DecodeTime(PresentUTC, nHours, nMins, nSecs, nMsecs);
    tod_Year := nYear;
    tod_Month := nMonth;
    tod_Day := nDay;
    tod_Hours := nHours;
    tod_Mins := nMins;
    tod_Secs := nSecs;
    tod_Hunds := nMsecs div 10;
    tod_Elapsedt := Round((PresentUTC - 25569) * 86400);
    tod_MSecs := GetTickCount;
    tod_TInterval := 1000;
    end
    else
    // fremder Rechner
    begin
    try
    IsWinNT := (Win32Platform = Ver_PlatForm_Win32_NT);
    if IsWinNT then
    // Rechner verwendet Windows NT
    begin
    ErrMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
    LibHandle := LoadLibrary(NTlib);
    SetErrorMode(ErrMode);
    if LibHandle = 0 then
    raise ENetTODError.Create(cLERROR + NTlib);
    @NTNetRemoteTOD := GetProcAddress(LibHandle, 'NetRemoteTOD');
    @NTNetApiBufferFree := GetProcAddress(LibHandle, 'NetApiBufferFree');
    StringtoWideChar(pChar(TimeServer), @wsSystem, sizeof(wsSystem));
    try
    NetCheck(NTNetRemoteTOD(@wsSystem, pTOD));
    TOD := pTOD^;
    finally
    NetCheck(NTNetApiBufferFree(pTOD));
    end;
    end
    else
    // Rechner verwendet Windows 95 mit Radmin32
    begin
    ErrMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
    LibHandle := LoadLibrary(Win95lib);
    SetErrorMode(ErrMode);
    if LibHandle = 0 then
    raise ENetTODError.Create(cLERROR + Win95lib);
    @NTNetRemoteTODA := GetProcAddress(LibHandle, 'NetRemoteTODA');
    @NTNetApiBufferFree := GetProcAddress(LibHandle, 'NetApiBufferFree');
    try
    NetCheck(NTNetRemoteTODA(pChar(TimeServer), pTOD));
    TOD := pTOD^;
    finally
    // pTOD = nil nach eine Exception, eventl. überflüssig
    NetCheck(NTNetApiBufferFree(pTOD));
    end;
    end;
    finally
    if LibHandle <> 0 then
    begin
    FreeLibrary(Libhandle);
    LibHandle := 0;
    end;
    end;
    end;
    end;

    function ServerTimeZoneOffset(ServerName: string): TDateTime;
    var
    TOD: TTimeofDayInfo;
    begin
    GetTOD(ServerName, TOD);
    Result := TOD.tod_TimeZone / MINUTESPERDAY;
    end;

    function ServerTime(ServerName: string): TDateTime;
    var
    TOD: TTimeofDayInfo;
    begin
    GetTOD(ServerName, TOD);
    with TOD do
    Result := EncodeDate(tod_Year, tod_Month, tod_Day) +
    EncodeTime(tod_Hours, tod_Mins, tod_Secs, tod_Hunds * 10);
    end;

    end.
    </pre&gt

    Comment


    • #3
      Hi Andreas

      Schön und gut, ich habe Win95 und keine RADMIN32.dll ??
      Ich habe Workgroups + Novel-Server + NT-Server Netzwerk, daran kanns also nicht scheitern. Alle üblichen Protokolle wie TCP/IP, NDISWAN, NetBEUI, IPX/SPX und Clienten sind installiert.

      Hagen

      PS: Ich hasse es wenn ich nicht sicher sein kann das solche DLL's zu System gehören. Funktioniert den NT/2000 denn richtig

      Comment


      • #4
        Hallo Herr Kosch und Herr Reddmann,

        genau um diese Probleme zu vermeiden, hatte ich an einen "unsichtbaren" Aufruf von NET gedacht. Der NET - Befehl funktioniert nach meinen Erfahrungen immer.

        Freundliche Grüße, Andreas Richte

        Comment


        • #5
          Unsichtbarer Aufruf von programm und umleitung des outputs in in eine Datei:<br>
          <br>
          procedure TForm2.testspeedClick(Sender: TObject);<br>
          var<br>
          aSA : TSecurityAttributes;<br>
          aSI : TStartupInfo;<br>
          aPI : TProcessInformation;<br>
          szTemp : array[0..199] of Char;<br>
          FName : String;<br>
          hLogFile : THandle;<br>
          dwExit : DWORD;<br>
          i,j :integer;<br>
          s :string;<br>
          tim :real;<br>
          <br>
          Procedure Loadit;<br>
          var r:integer;<br>
          begin<br>
          if getmyfilesize(FName)<5 then exit;<br>
          //funtioniert nicht, wenn datei noch geschrieben wird:<br>
          //foutput.free;<br>
          //foutput:=TStringList.Create;<br>
          //foutput.LoadFromFile(FName);<br>
          //foutput.free;<br>
          FileMode:=0;<br>
          assignfile(rsrctxt,dateiname);<br>
          reset(rsrctxt);<br>
          .....readln in array datei<br>
          <br>
          closefile(rsrctxt);<br>
          end;<br>
          <br>
          Begin<br>
          <br>
          FillChar(aSA, SizeOf(aSA), #0);<br>
          aSA.nLength := SizeOf(aSA);<br>
          aSA.bInheritHandle := True;<br>
          <br>
          // temp. Dateinamen für Output generieren<br>
          FillChar(szTemp, SizeOf(szTemp), #0);<br>
          GetEnvironmentVariable(PCHar('TEMP'), szTemp, 180);<br>
          FName := szTemp + '\MRay.txt';<br>
          // Output-Datei öffnen<br>
          hLogFile := CreateFile(PCHar(FName), GENERIC_WRITE or GENERIC_READ,
          FILE_SHARE_READ or FILE_SHARE_WRITE,
          @aSA, CREATE_ALWAYS, 0, 0);<br>
          // Standard-Output in Datei umleiten<br>
          {FillChar(aSI, SizeOf(aSI), 0);<br>
          aSI.cb := SizeOf(aSI);aSI.lpReserved:=nil;aSI.lpDesktop:=nil ;<br>
          aSI.lpReserved2:=nil;aSi.cbReserved2:=0;}<br>
          GetStartupInfo(aSI);<br>
          aSI.dwflags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;<br>
          aSI.wShowWindow := SW_SHOWNORMAL;//<= aendern, wenn garnichts zu sehen sein soll <br>
          aSI.hStdOutput := hLogFile;<br>
          aSI.hStdError := hLogFile;<br>
          <br>
          ASI.lpTitle:=pchar('No output visible, can take a few minutes');<br>
          i:=1;<br>
          if CreateProcess(PChar(ppfad+'bat\c_'+computername+'. bat'), nil, nil, nil, True, Normal_Priority_Class, nil, PChar(ppfad), aSI, aPI)<br>
          then
          begin<br>
          repeat<br>
          Application.ProcessMessages;<br>
          sleep(1000);<br>
          GetExitCodeProcess(aPI.hProcess, dwExit);<br>
          inc(i);<br>
          if i mod 5=0 then<br>
          begin<br>
          i:=1;<br>
          loadit;<br>
          end;<br>
          until dwExit <> STILL_ACTIVE;<br>
          CloseHandle(aPI.hThread);<br>
          CloseHandle(aPI.hProcess);<br>
          CloseHandle(hLogFile);<br>
          end<br>
          else exit;<br>
          sleep(200);<br>
          if getmyfilesize(FName)<30 then<br>
          begin<br>
          Showmessage('No verbose file was created, can''t calculate');<br>
          exit;<br>
          end;<br>
          loadit;<br>
          i:=1;<br>
          //While (i<(foutput.count-1)) and (pos('TIME',upstring(foutput.Strings[i]))<=0) do inc(i);<br>
          While (i<maxdatei) and (pos('TIME',upstring(datei[i]))<=0) do inc(i);<br>
          if (pos('TIME',upstring(datei[i]))=0) then<br>
          begin<br>
          Showmessage('Not found');<br>
          end<br>
          else<br>
          begin<br>
          s:=datei[i];<br>
          auslesen<br>
          end;<br>
          //foutput.free;<br>
          //foutput:=nil;<br>
          DeleteFile(FName);<br>
          end;<br&gt

          Comment


          • #6
            Hi,

            Noch kürzer ist's doch wohl, die Arbeitsstation so zu konfigurieren, dass sie sich beim Anmelden das Systemdatum automatisch vom Server holt. Danach reicht ein Aufruf von Time().

            Gruß
            Gesin

            Comment

            Working...
            X