【问题标题】:When did my application start running?我的应用程序是什么时候开始运行的?
【发布时间】:2009-11-12 20:48:17
【问题描述】:

获取应用程序执行日期和时间的函数是什么?我正在使用 Delphi。

【问题讨论】:

  • 什么“启动时间”?你可以说得更详细点吗?您是否正在寻找您的申请需要多长时间才能启动?或者是一天中什么时候开始的?
  • 是的,它开始的时间。
  • 彼得,你的问题并不是 Delphi 特有的,答案也不是,所以我改变了这个问题,所以非 Delphi 程序员不太可能将其视为无关紧要。一个类似的问题。
  • Rob,我有点希望这个问题是 Delphi 特有的。我希望有像 Application.GetUpTime() 这样的东西。 GetProcessTimes 是一个非常神秘的函数,为了转换为 TDateTime,需要使用 FileTimeToSystemTime 和 SystemTimeToDateTime。但是,就是这样啊?

标签: delphi winapi


【解决方案1】:

您可以使用对GetProcessTimes(在 Windows.pas 中声明)的 Windows API 调用来获取任何进程的详细信息。

如果是您的应用程序,我可能会自己获取开始时间并将其记录在某个地方以保留历史记录。

【讨论】:

【解决方案2】:

我不确定是否对此有函数或 API 调用。但是你可以很容易地伪造它。创建一个如下所示的单元:

unit AppStartTime;

interface

function GetAppStartTime: TDateTime;

implementation
uses
  SysUtils;

var
  fStartTime: TDateTime;

function GetAppStartTime: TDateTime;
begin
  result := fStartTime;
end;

initialization
  fStartTime := Now;

end.

将其添加到您的 DPR 的使用列表的顶部,无论是“必须是列表中的第一位”,还是任何“必须在列表中的第一位”(例如自定义内存管理器)之后立即添加。

【讨论】:

  • 如果你想真正准确,并且你的应用程序启动时间很长,那么把这个单元放在你的uses子句中。
  • 如果你想真的准确,你需要使用GetProcessTimes(),因为即使是第一个单元的初始化代码也只有在所有模块都完成后才会执行已加载并且所有模块入口点都已解析,这可能需要相当长的时间,因为 I/O 带宽低且没有任何预加载或缓存。
【解决方案3】:

将 NtQuerySystemInformation 与 SystemProcessInformation 信息类一起使用,这将返回一个 SYSTEM_PROCESSES 结构(记录)数组,其中 CreateTime 包含应用程序启动的确切时间:

  _SYSTEM_PROCESSES = record // Information Class 5
    NextEntryDelta: ULONG;
    ThreadCount: ULONG;
    Reserved1: array[0..5] of ULONG;
    CreateTime: LARGE_INTEGER;
    UserTime: LARGE_INTEGER;
    KernelTime: LARGE_INTEGER;
    ProcessName: UNICODE_STRING;
    BasePriority: KPRIORITY;
    ProcessId: ULONG;
    InheritedFromProcessId: ULONG;
    HandleCount: ULONG;
    // next two were Reserved2: array [0..1] of ULONG; thanks to Nico Bendlin
    SessionId: ULONG;
    Reserved2: ULONG;
    VmCounters: VM_COUNTERS;
    PrivatePageCount: ULONG;
    IoCounters: IO_COUNTERSEX; // Windows 2000 only
    Threads: array[0..0] of SYSTEM_THREADS;
  end;
  SYSTEM_PROCESSES = _SYSTEM_PROCESSES;
  PSYSTEM_PROCESSES = ^SYSTEM_PROCESSES;
  TSystemProcesses = SYSTEM_PROCESSES;
  PSystemProcesses = PSYSTEM_PROCESSES;

我们已经在 J​​edi Apilib (JwaNative) 中翻译了所有这些内容

【讨论】:

  • 这不是 MSDN 上记录的结构,所以我不敢相信它的准确性。
  • 嗯,微软一直没有记录这个功能,现在他们部分记录了。结构在很久以前就被颠倒了,所以我认为使用起来非常安全。
  • 非常感谢 Remko,您能否告诉我们更多关于如何从 CreateTime 转换为系统时间的信息,是自纪元以来的微秒数? PS - 确切的结构在这里 - processhacker.sourceforge.net/doc/…
  • FileTimeToLocalFileTime -> FileTimeToSystemTime -> SystemTimeToDateTime
  • 非常感谢先生如此及时的回复!由衷感谢!您能否再解释一下,可能举个例子,我应该提出单独的问题吗?这就是我正在做的事情 - msSinceEpoch = (CreateTime - 116444736000000000) / 10000 它似乎有效,但我不明白。
【解决方案4】:

您可以让您的应用程序在 DPR 文件或主窗体的 OnCreate() 事件中将启动时间记录到文本文件或数据库中。您可以使用 Delphi 的 Now() 函数获取当前日期和时间,并使用 FormatDateTime() 或 DateTimeToStr() 将其格式化为字符串,具体取决于您要执行的操作。

下面的代码在主窗体的构造函数中将启动日期和时间保存到与应用程序本身位于同一文件夹中的名为 StartDateTime.txt 的文本文件中:

procedure TForm1.FormCreate(Sender: TObject);
var
  SL: TStringList;
begin
  SL := TStringList.Create;
  try
    SL.Add(FormatDateTime('mm/dd/yyyy hh:nn:ss', Now());
    SL.SaveToFile(ExtractFilePath(ParamStr(0)) + 'StartDateTime.txt');
  finally
    SL.Free;
  end;
end;

【讨论】:

  • 你的回答和布鲁斯矛盾吗?
  • 彼得。不。他的回答接近我回答的第二部分,除了肯发布了他的第一个并包含源代码。如果这是您选择的方式,您应该选择 Ken 的答案作为正确答案。
  • 我仍然希望删除答案的第一句话——这显然是错误的。
  • @mghie:完成。我错过了 GetProcessTimes()。过失。
  • @Bruce:实际上,你的答案更好。我的只是在 GetProcessTimes() 可用之前的 Windows 版本上更好。 :-)
猜你喜欢
  • 2013-11-11
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 2016-12-01
  • 2012-12-16
  • 2015-09-10
  • 2018-07-04
  • 2011-05-16
相关资源
最近更新 更多