Ustalenie czasu pracy systemu w latach

0

Jak w Delphi ustalić czas pracy systemu jeśli komputer działa już ponad 280 dni?
Takie funkcje jak TimeGetTime() czy GetTickCount() na nic się nie przydają bo zwracają
czas pracy systemu w milisekundach ale do wartości maksymalnie $FFFFFFFF

Polecenie konsoli systeminfo zwraca prawidłowo ilość dni.
Czy istnieje funkcja zwracająca np. sekundy od startu systemu?
Format jaki chce uzyskać to lata,miesiace,tygodnie,dni,godziny,minuty

0

Chodzi o systemy Win 2000,Win 2003, i np: XP a tam nie ma GetTickCount64()

0

Tak to doskonale działa jutro zrobie testy pod WinNT,Win2000,Win2003 dzięki Pozdrawiam.

0

Czas startu systemu i czas pracy systemu windows.

To gotowy przykład działa doskonale nawet w przypadku wieloletniej pracy serwera zwraca prawidłowy czas.
Wstawiam gotowca na podstawie zebranych tu informacji.
Pozdrawiam.

 

///////////////////////////////////////////////////////////////////////////////////////////////////////
//Ustal sekundy od startu systemu operacyjnego.
function UpSecondsLastBoot: int64;
var
  cnt, freq: Int64;
begin
     QueryPerformanceCounter(cnt);
     QueryPerformanceFrequency(freq);
     Result := (cnt div freq);
end;

///////////////////////////////////////////////////////////////////////////////////////////////////////

function UptimeInDays: double;
const
  c_SecondsInADay = 86400;
var
  cnt, freq: Int64;
begin
  QueryPerformanceCounter(cnt);
  QueryPerformanceFrequency(freq);
  Result := (cnt / freq) / c_SecondsInADay;
end;

function LastBootTime: TDateTime;
begin
  Result := Now() - UptimeInDays;

end;

///////////////////////////////////////////////////////////////////////////////////////////////////////
//Wersja 1.0 nie optymizowana
//Funkcja zamienia sekundy na przyswajalny przelicznik czasowy.

function FormatSeconds(TotalSeconds :comp; WholeSecondsOnly, DisplayAll, DTFormat :Boolean) :String;
var
 lcenturies,lyears,lmonths,lminutes,lhours,ldays,lweeks :word;
 lSecs :double;
 s :array[1..8] of string;
 SecondsPerCentury :comp;
 FS :string;
begin
  if WholeSecondsOnly then
    FS:='%.0f'
  else
    FS:='%.2f';
  SecondsPerCentury:=36550 * 24;
  SecondsPerCentury:= SecondsPerCentury * 3600;
  lcenturies:=Trunc(TotalSeconds / SecondsPerCentury);
  TotalSeconds:=TotalSeconds-(lcenturies * SecondsPerCentury);
  lyears:=Trunc(TotalSeconds / (365.5 * 24 * 3600));
  TotalSeconds:=TotalSeconds-(lyears * (365.5 * 24 * 3600));
  lmonths:=Trunc(TotalSeconds / (31 * 24 * 3600));
  TotalSeconds:=TotalSeconds-(lmonths * (31 * 24 * 3600));
  lweeks:=Trunc(TotalSeconds / (7 * 24 * 3600));
  TotalSeconds:=TotalSeconds-(lweeks * (7 * 24 * 3600));
  ldays:=Trunc(TotalSeconds / (24 * 3600));
  TotalSeconds:=TotalSeconds-(ldays * (24 * 3600));
  lhours:=Trunc(TotalSeconds / 3600);
  TotalSeconds:=TotalSeconds-(lhours * 3600);
  lminutes:=Trunc(TotalSeconds / 60);
  TotalSeconds:=TotalSeconds-(lminutes * 60);
  If WholeSecondsOnly then
    lsecs:=Trunc(TotalSeconds)
  else
    lsecs:=TotalSeconds;
  if lCenturies=1 then
    s[1]:=' Stulecie, '
  else
    s[1]:=' Stulecia, ';
  if lyears=1 then
    s[2]:=' Rok, '
  else
    s[2]:=' Lata, ';
  if lmonths=1 then
    s[3]:=' Miesiąc, '
  else
    s[3]:=' Miesiące, ';
  if lweeks=1 then
    s[4]:=' Tydzień, '
  else
    s[4]:=' Tygodnie, ';
  if ldays=1 then
    s[5]:=' Dzień, '
  else
    s[5]:=' Dni, ';
  if lhours=1 then
    s[6]:=' Godzina, '
  else
    s[6]:=' Godziny, ';
  if lminutes=1 then
    s[7]:=' Minuta, '
  else
    s[7]:=' Minuty, ';
  if lsecs=1 then
    s[8]:=' Sekunda.'
  else
    s[8]:=' Sekundy.';
  If DisplayAll then begin
    if dtformat then
      result:=Format('%2.2d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d',
                     [lyears,lmonths,ldays+lweeks*7,lhours,lminutes,round(lSecs)])
    else
      Result:= Format('%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s' + FS + '%s',
                     [lcenturies,s[1],lyears,s[2],lmonths,s[3],lweeks,s[4],ldays,s[5],lhours,s[6],lminutes,s[7],lSecs,s[8]]);

  end else begin
    if dtformat then
      result:=Format('%2.2d:%2.2d:%2.2d',
                     [lhours,lminutes,round(lSecs)])
    else begin
      if lCenturies>=1 then
        Result:= Format('%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s' + FS + '%s',
                        [lcenturies,s[1],lyears,s[2],lmonths,s[3],lweeks,s[4],ldays,s[5],lhours,s[6],lminutes,s[7],lsecs,s[8]])
      else
        if lyears>=1 then
          Result:= Format('%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s' + FS + '%s',
                          [lyears,s[2],lmonths,s[3],lweeks,s[4],ldays,s[5],lhours,s[6],lminutes,s[7],lsecs,s[8]])
      else
       if lmonths>=1 then
         Result:= Format('%.0d%s%.0d%s%.0d%s%.0d%s%.0d%s' + FS + '%s',
                         [lmonths,s[3],lweeks,s[4],ldays,s[5],lhours,s[6],lminutes,s[7],lsecs,s[8]])
       else
         if lweeks>=1 then
           Result:= Format('%.0d%s%.0d%s%.0d%s%.0d%s' + FS + '%s',
                           [lweeks,s[4],ldays,s[5],lhours,s[6],lminutes,s[7],lsecs,s[8]])
         else
           if ldays>=1 then
             Result:= Format('%.0d%s%.0d%s%.0d%s' + FS + '%s',
                             [ldays,s[5],lhours,s[6],lminutes,s[7],lsecs,s[8]])
           else
             if lhours>=1 then
               Result:= Format('%.0d%s%.0d%s' + FS + '%s',
                               [lhours,s[6],lminutes,s[7],lsecs,s[8]])
             else
               if lminutes>=1 then
                 Result:= Format('%.0d%s' + FS + '%s',[lminutes,s[7],lsecs,s[8]])
               else
                 Result:= Format(FS + '%s',[lsecs,s[8]]);
    end;
  end;
end;
///////////////////////////////////////////////////////////////////////////////////////////////////////





procedure TForm1.Button1Click(Sender: TObject);
begin

      Label1.Caption:='Data czas startu systemu: '+FormatDateTime('yyyy-mm-dd hh:nn:ss',LastBootTime);
      Label2.Caption:='Czas od startu komputera: '+FormatSeconds(UpSecondsLastBoot,True,True,False);

end;

1

Trzeba doprecyzować pewną rzecz: HPET (z którego korzysta QueryPerformanceCounter) jest sprzętowym licznikiem, który w stałych odstępach czasu zwiększa pewną wartość o stałą liczbę. Co więcej, może on pracować w trybie 32 lub 64 bitowym (może się on prędzej czy później "przekręcić") oraz nie jest sprecyzowana jego praca w poszczególnych typach stanu wstrzymania. Może on podczas nich działać bądź nie, zachować swoją wartość bądź nie.
Mając powyższe na uwadze trzeba pamiętać, że HPET wcale nie musi nam pozwolić na obliczenie uptime.

Specyfikacja HPET napisał(a)

The Event Timer registers (including the main counter) are not expected to be preserved through an S3, S4, or S5 state.
The main counter is permitted, but not required, to run during S1 or S2 states. This allows mobile systems to stop clock generators feeding the main counter during S1 or S2 states.
Reads to this register are monotonic. No two consecutive reads will return the same value, except when the reads happen at less than the resolution of the counter or if the counter has rolled over.

Jeżeli miałbym polecić jakieś rozwiązanie to byłoby to przeczytanie wartości performance counter o nazwie, uwaga: System Up Time ;).

1 użytkowników online, w tym zalogowanych: 0, gości: 1