2

如何在 Windows 2008/2003 机器上获取上次启动/重启/重启的日期和时间?

我从命令提示符知道我们可以使用“网络统计”,但是如何通过 Delphi 来做到这一点?

谢谢。

4

4 回答 4

7

您可以使用 WMI 类的LastBootUpTime属性,它返回(注意:该属性的返回值是 UTC 格式)。Win32_OperatingSystemDate and time the operating system was last restarted

检查此示例应用程序

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  Variants,
  ComObj;


//Universal Time (UTC) format of YYYYMMDDHHMMSS.MMMMMM(+-)OOO.
//20091231000000.000000+000
function UtcToDateTime(const V : OleVariant): TDateTime;
var
  Dt : OleVariant;
begin
  Result:=0;
  if VarIsNull(V) then exit;
  Dt:=CreateOleObject('WbemScripting.SWbemDateTime');
  Dt.Value := V;
  Result:=Dt.GetVarDate;
end;

procedure  GetWin32_OperatingSystemInfo;
const
  WbemUser            ='';
  WbemPassword        ='';
  WbemComputer        ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_OperatingSystem','WQL',wbemFlagForwardOnly);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  if oEnum.Next(1, FWbemObject, iValue) = 0 then
  begin
    Writeln(Format('Last BootUp Time    %s',[FWbemObject.LastBootUpTime]));// In utc format
    Writeln(Format('Last BootUp Time    %s',[formatDateTime('dd-mm-yyyy hh:nn:ss',UtcToDateTime(FWbemObject.LastBootUpTime))]));// Datetime
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_OperatingSystemInfo;
    finally
      CoUninitialize;
    end;
 except
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.
于 2011-06-29T15:53:26.557 回答
3

这是一个完整的命令行应用程序,可以满足您的要求。我已经对此进行了修改,以避免在不依赖外部函数调用的情况下出现 GetTickCount 溢出问题。

示例输出:

Windows was last rebooted at: 06/29/2011 9:22:47 AM

玩得开心!

program lastboottime;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows;

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;

begin
  try
    WriteLn('Windows was last rebooted at: ' + DateTimeToStr(LastBootTime));
    ReadLn;
  except on E: Exception do
    Writeln(E.ClassName, ': ', E.Message);
  end;
end.
于 2011-06-29T13:55:19.743 回答
1

GetTickCount函数(请参阅MSDN)返回自系统启动以来经过的毫秒数,因此将其除以 1000 以获取秒数,除以 60 000 以获取分钟数等。

我链接的主题也包含这一点:

要获取自计算机启动以来经过的时间,请在注册表项 HKEY_PERFORMANCE_DATA 的性能数据中检索系统运行时间计数器。返回的值是一个 8 字节的值。有关详细信息,请参阅性能计数器。

于 2011-06-29T13:31:55.517 回答
1

这是一些代码,GetTickCount64如果可用则使用,如果不可用则回退到GetTickCount计算系统启动的日期和时间。这不是一个完美的解决方案,因为GetTickCount64仅在 Vista+ 上受支持:如果您使用的是较旧的 Windows,则计数器每 49 天返回 0。

program Project29;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

type
  TGetTickCount64 = function : Int64; stdcall;

var
  H_K32: HMODULE;
  Tick64Proc: TGetTickCount64;

function BootTime: TDateTime;
var UpTime: Int64;
    Seconds, Minutes, Hours: Int64;
begin
  if H_K32 = 0 then
  begin
    H_K32 := LoadLibrary(kernel32);
    if H_K32 = 0 then
      RaiseLastOSError
    else
      begin
        Tick64Proc := GetProcAddress(H_K32, 'GetTickCount64');
     end;
  end;

  if Assigned(Tick64Proc) then
    UpTime := Tick64Proc
  else
    UpTime := GetTickCount;

  Result := Now - EncodeTime(0, 0, 0, 1) * UpTime;
end;

begin
  WriteLn(DateTimeToStr(BootTime));
  ReadLn;
end.
于 2011-06-29T13:54:37.617 回答