全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2100
推到 Plurk!
推到 Facebook!

如何知道Windows系統開運作時間(如果開機超過49.7天)

尚未結案
guru1979
一般會員


發表:1
回覆:0
積分:0
註冊:2005-03-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-03-06 22:35:02 IP:220.139.xxx.xxx 未訂閱
我想請問一下: 怎麼樣知道Windows系統已經開機運作了多久 使用GetTickCount()的問題在於如果開機超過49.7天後就會歸0 後來想用GetProcessTimes()來抓System Idle Process 的生成時間. 可是OpenProcess就不讓我開(with PID = 0 ) 而且Windows 98似乎也不支援GetProcessTimes() 因此想請問一下有沒有什麼API或其他手段可以達到我的目的. 謝謝
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-03-07 07:29:59 IP:218.19.xxx.xxx 未訂閱
guru1979: 如果您不是非要在程式中計算開機使用時間的話,可以使用名為 uptime 的工具程式來獲得相關資訊,這種程式很多,您可以使用 uptime 為關鍵字透過搜尋引擎找到不少,Microsoft 也有提供指令行 (Command Line) 工具,我在 MS 網站的搜尋框輸入 uptime 字樣所找到的程式僅有 46KB (支援 NT4 SP4 或更新的系統),您參考一下吧。 附註: 1. 既然該程式能獲知開機使用時間,那麼理論上應該也可以由自己撰寫程式來取得的,如果您需要將該功能寫在程式內的話,或許也可以試著透過網路來找找相關資訊。 2. 如果必須要在程式內使用該功能,而且也急著用的話,那麼不妨再找到相關資料之前,先由程式內呼叫 uptime.exe 來執行,然後將輸出結果導向至一個文字檔,再由程式讀入該文字檔,這樣子就可以拆解出相關數據來使用了。
brook
資深會員


發表:57
回覆:323
積分:371
註冊:2002-07-12

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-03-08 08:31:56 IP:218.160.xxx.xxx 未訂閱
假如GetTickCount()可以用,那用Now()應該也行.
chris_shieh
高階會員


發表:46
回覆:308
積分:240
註冊:2004-04-26

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-03-08 19:04:53 IP:219.68.xxx.xxx 未訂閱
如果還是想要用原來方法 那就先把得到的天數存起來囉
var
  Form1: TForm1;
  preTickCount :DWORD;
  UpDays:Extended; //TDatetime
  bProcessDWORDLimit:Boolean;    implementation    {$R *.dfm}    uses ...Math, DateUtil...    function TimeStrInBetween(time1, time2: TDatetime):String;
var
  days, year,mon,day, h, m, s, ms:Word;
begin
  DivMod(DaysBetween(time1, time2), 365 , year, days); //精簡一下
  DivMod(days, 30, mon, day); //精簡一下
  DecodeTime(time1-time2,h,m,s,ms);
  Result:=Format('%d  年, %d 月, %d 日, %d 小時, %d 分, %d 秒', [year, mon, day, h, m, s]);
end;    procedure TForm1.Timer1Timer(Sender: TObject);
var
  dtElapse:TDatetime;
begin
  if (not bProcessDWORDLimit) and ((MAXDWORD - GetTickCount)<=10000) then //到49.7天10秒前先將天數存起來
  begin
    UpDays:=MAXDWORD / (1000*60*60*24); //約等於49.7天後面有一堆小數點
    preTickCount:=GetTickCount;
    bProcessDWORDLimit:=True;
  end;      if bProcessDWORDLimit and ((GetTickCount-preTickCount)<0) then //預存天數後 歸零發生
    bProcessDWORDLimit:=False;      dtElapse:=UpDays   GetTickCount / (1000*60*60*24);      Label1.Caption:=TimeStrInBetween(0, dtElapse);
end;    
不過這方法遇到GetTickCount歸零過的電腦就沒用拉 真正要得到這個訊息 根據Delphi 所附的Windows SDK Help 可以去讀取registry, Windows會一直去update HKEY_PERFORMANCE_DATA 內的 資料 [GetTickCount] Windows NT: To obtain the time elapsed since the computer was started, look up the System Up Time counter in the performance data in the registry key HKEY_PERFORMANCE_DATA. The value returned is an 8 byte value. 可以參考這裡有完整的函式與範例 http://www.delphipraxis.net/topic16973.html
//////////////////////////////////////////////////////////////////////////////// 
// 
//  GetSystemUpTimeNt() 
// 
//    Uses the registry interface to get the value of the performance counter 
//    '\\localhost\System\System Up Time' in milliseconds (returns 0 on error). 
//     function GetSystemUpTimeNt(): Int64; 
{$IFDEF WIN32} 
type 
  PPerfDataBlock = ^TPerfDataBlock; 
  TPerfDataBlock = packed record 
    Signature       : array [0..3] of WCHAR; 
    LittleEndian    : DWORD; 
    Version         : DWORD; 
    Revision        : DWORD; 
    TotalByteLength : DWORD; 
    HeaderLength    : DWORD; 
    NumObjectTypes  : DWORD; 
    DefaultObject   : DWORD; 
    SystemTime      : SYSTEMTIME; 
    PerfTime        : LARGE_INTEGER; 
    PerfFreq        : LARGE_INTEGER; 
    PerfTime100nSec : LARGE_INTEGER; 
    SystemNameLength: DWORD; 
    SystemNameOffset: DWORD; 
  end; 
  PPerfObjectType = ^TPerfObjectType; 
  TPerfObjectType = packed record 
    TotalByteLength     : DWORD; 
    DefinitionLength    : DWORD; 
    HeaderLength        : DWORD; 
    ObjectNameTitleIndex: DWORD; 
    ObjectNameTitle     : LPWSTR; 
    ObjectHelpTitleIndex: DWORD; 
    ObjectHelpTitle     : LPWSTR; 
    DetailLevel         : DWORD; 
    NumCounters         : DWORD; 
    DefaultCounter      : DWORD; 
    NumInstances        : DWORD; 
    CodePage            : DWORD; 
    PerfTime            : LARGE_INTEGER; 
    PerfFreq            : LARGE_INTEGER; 
  end; 
  PPerfCounterDefinition = ^TPerfCounterDefinition; 
  TPerfCounterDefinition = packed record 
    ByteLength           : DWORD; 
    CounterNameTitleIndex: DWORD; 
    CounterNameTitle     : LPWSTR; 
    CounterHelpTitleIndex: DWORD; 
    CounterHelpTitle     : LPWSTR; 
    DefaultScale         : DWORD; 
    DetailLevel          : DWORD; 
    CounterType          : DWORD; 
    CounterSize          : DWORD; 
    CounterOffset        : DWORD; 
  end; 
  PPerfInstanceDefinition = ^TPerfInstanceDefinition; 
  TPerfInstanceDefinition = packed record 
    ByteLength            : DWORD; 
    ParentObjectTitleIndex: DWORD; 
    ParentObjectInstance  : DWORD; 
    UniqueID              : DWORD; 
    NameOffset            : DWORD; 
    NameLength            : DWORD; 
  end; 
  PLARGE_INTEGER = ^LARGE_INTEGER; 
const 
  PERF_SIZE_LARGE      = $00000100; 
  PERF_TYPE_COUNTER    = $00000400; 
  PERF_COUNTER_ELAPSED = $00040000; 
  PERF_OBJECT_TIMER    = $00200000; 
  PERF_DISPLAY_SECONDS = $30000000; 
  PERF_ELAPSED_TIME    = PERF_SIZE_LARGE or PERF_TYPE_COUNTER or 
                         PERF_COUNTER_ELAPSED or PERF_OBJECT_TIMER or 
                         PERF_DISPLAY_SECONDS; 
  PERF_NO_INSTANCES = DWORD(-1); 
var 
  ValSize: DWORD; 
  Counter: PChar; 
  CurrIdx: PChar; 
  CurrStr: PChar; 
  CntrStr: PChar; 
  CntrSys: DWORD; 
  CntrSUT: DWORD; 
  QrySize: DWORD; 
  QryData: PPerfDataBlock; 
  CurrObj: PPerfObjectType; 
  ObjLoop: DWORD; 
  CurrDef: PPerfCounterDefinition; 
  DefLoop: DWORD; 
  ObjInst: PPerfInstanceDefinition; 
  CntrVal: PLARGE_INTEGER; 
{$ENDIF} 
begin 
  Result := 0;  // indicates failure 
{$IFDEF WIN32} 
  ValSize := 0; 
  if (RegQueryValueEx(HKEY_PERFORMANCE_DATA, 'Counter 009', nil, nil, nil, 
    @ValSize) = ERROR_SUCCESS) then 
  try 
    Inc(ValSize, 1024); 
    Counter := GetMemory(ValSize); 
    if (Counter <> nil) then 
    try 
      if (RegQueryValueEx(HKEY_PERFORMANCE_DATA, 'Counter 009', nil, nil, 
        PByte(Counter), @ValSize) = ERROR_SUCCESS) then 
      begin 
        CntrStr := nil; 
        CntrSys := 0; 
        CntrSUT := 0; 
        CurrIdx := Counter; 
        while (CurrIdx[0] <> #0) do 
        begin 
          CurrStr := PChar(@CurrIdx[StrLen(CurrIdx)   1]); 
          if ((CntrSys = 0) and (StrComp(CurrStr, 'System') = 0)) then 
          begin 
            CntrStr := CurrIdx; 
            CntrSys := StrToInt(string(CurrIdx)); 
            if (CntrSUT <> 0) then 
              Break; 
          end; 
          if ((CntrSUT = 0) and (StrComp(CurrStr, 'System Up Time') = 0)) then 
          begin 
            CntrSUT := StrToInt(string(CurrIdx)); 
            if (CntrSys <> 0) then 
              Break; 
          end; 
          CurrIdx := PChar(@CurrStr[StrLen(CurrStr)   1]); 
        end; 
        if ((CntrStr <> nil) and (CntrSys <> 0) and (CntrSUT <> 0)) then 
        begin 
          QrySize := 0; 
          QryData := nil; 
          try 
            repeat 
              Inc(QrySize, 4096); 
              QryData := ReallocMemory(QryData, QrySize); 
              if (QryData = nil) then 
                Break; 
              ValSize := QrySize; 
            until (RegQueryValueEx(HKEY_PERFORMANCE_DATA, CntrStr, nil, nil, 
              PByte(QryData), @ValSize) <> ERROR_MORE_DATA); 
            if ((ValSize > 0) and (QryData <> nil)) then 
              if (QryData.Signature = 'PERF') then 
              begin 
                CurrObj := PPerfObjectType(Cardinal(QryData)   
                  QryData.HeaderLength); 
                for ObjLoop := 1 to QryData.NumObjectTypes do 
                begin 
                  if ((CurrObj.ObjectNameTitleIndex = CntrSys) and 
                    (CurrObj.NumInstances > 0) and 
                    (CurrObj.PerfFreq.QuadPart >= 1000)) then 
                  begin 
                    CurrDef := PPerfCounterDefinition(Cardinal(CurrObj)   
                      CurrObj.HeaderLength); 
                    for DefLoop := 1 to CurrObj.NumCounters do 
                    begin 
                      if (CurrDef.CounterNameTitleIndex = CntrSUT) and 
                        (CurrDef.CounterType = PERF_ELAPSED_TIME) then 
                      begin 
                        if (CurrObj.NumInstances = PERF_NO_INSTANCES) then 
                          CntrVal := PLARGE_INTEGER(Cardinal(CurrObj)   
                             CurrObj.DefinitionLength   CurrDef.CounterOffset) 
                        else 
                        begin 
                          // first instance 
                          ObjInst := PPerfInstanceDefinition(Cardinal(CurrObj)   
                            CurrObj.DefinitionLength); 
                          CntrVal := PLARGE_INTEGER(Cardinal(ObjInst)   
                             ObjInst.ByteLength   CurrDef.CounterOffset); 
                        end; 
                        Result := 
                          (CurrObj.PerfTime.QuadPart - CntrVal.QuadPart) div 
                          (CurrObj.PerfFreq.QuadPart div 1000);  // milliseconds 
                        Break; 
                      end; 
                      CurrDef := PPerfCounterDefinition(Cardinal(CurrDef)   
                        CurrDef.ByteLength); 
                    end; 
                    Break; 
                  end; 
                  CurrObj := PPerfObjectType(Cardinal(CurrObj)   
                    CurrObj.TotalByteLength); 
                end; 
              end; 
          finally 
            if (QryData <> nil) then 
              FreeMemory(QryData); 
          end; 
        end; 
      end; 
    finally 
      FreeMemory(Counter); 
    end; 
  finally 
    RegCloseKey(HKEY_PERFORMANCE_DATA); 
  end; 
{$ENDIF} 
end;     //////////////////////////////////////////////////////////////////////////////// 
// 
//  GetSystemUpTime9x() 
// 
//    Uses GetTickCount() to get the 'System Up Time' in milliseconds. 
//    Will wrap around to zero if the system is run continuously for 49.7 days! 
//     function GetSystemUpTime9x(): Int64; 
begin 
{$IFDEF WIN32} 
  Result := GetTickCount(); 
{$ELSE} 
  Result := 0; 
{$ENDIF} 
end;     //////////////////////////////////////////////////////////////////////////////// 
// 
//  GetSystemUpTime() 
// 
//    Wrapper for GetSystemUpTimeNt() and GetSystemUpTime9x() 
//     function GetSystemUpTime(): Int64; 
begin 
  Result := GetSystemUpTimeNt(); 
  if (Result = 0) then 
    Result := GetSystemUpTime9x(); 
end;     //////////////////////////////////////////////////////////////////////////////// 
// Sample     procedure TForm1.Button1Click(Sender: TObject); 
var 
  UpTimeNt: Int64; 
  UpTime9x: Int64; 
begin 
  UpTime9x := GetSystemUpTime9x(); 
  UpTimeNt := GetSystemUpTimeNt(); 
  ShowMessage(Format('GetTickCount: %d day(s) %2.2d:%2.2d:%2.2d.%3.3d'#10   
    'Perf-Counter: %d day(s) %2.2d:%2.2d:%2.2d.%3.3d', [UpTime9x div 86400000, 
    UpTime9x mod 86400000 div 3600000, UpTime9x mod 3600000 div 60000, 
    UpTime9x mod 60000 div 1000, UpTime9x mod 1000, UpTimeNt div 86400000, 
    UpTimeNt mod 86400000 div 3600000, UpTimeNt mod 3600000 div 60000, 
    UpTimeNt mod 60000 div 1000, UpTimeNt mod 1000])); 
end;
@瞭解越多.懂得越少@
系統時間:2024-04-25 9:36:25
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!