【问题标题】:Retrieving boot time using GetTickCount64使用 GetTickCount64 检索启动时间
【发布时间】:2011-07-21 15:13:42
【问题描述】:

我试图通过获取当前时间 SYSTEMTIME 结构来提取启动时间,然后将其转换为 FILETIME,然后我将其转换为 ULARGE_INTEGER,从中减去 GetTickCount64(),然后继续将所有内容转换回 SYSTEMTIME。

我将此函数与“NET STATISTICS WORKSTATION”进行比较,由于某种原因,我的输出延迟了几个小时,这似乎与任何时区差异都不匹配。

这是 Visual Studio 示例代码:

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define KILOBYTE 1024
#define BUFF KILOBYTE


int _tmain(int argc, _TCHAR* argv[])
{
    ULARGE_INTEGER ticks, ftime;
    SYSTEMTIME current, final;
    FILETIME ft, fout;

    OSVERSIONINFOEX osvi;

    char output[BUFF];
    int retval=0;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    ZeroMemory(&final, sizeof(SYSTEMTIME));
    GetVersionEx((OSVERSIONINFO *) &osvi);

    if (osvi.dwBuildNumber >= 6000) ticks.QuadPart = GetTickCount64();
    else ticks.QuadPart = GetTickCount();
    //Convert miliseconds to 100-nanosecond time intervals
    ticks.QuadPart = ticks.QuadPart * 10000;
    //GetLocalTime(&current); -- //doesn't really fix the problem
    GetSystemTime(&current);
    SystemTimeToFileTime(&current, &ft);
    printf("INITIAL: Filetime lowdatetime %u, highdatetime %u\r\n", ft.dwLowDateTime, ft.dwHighDateTime);
    ftime.LowPart=ft.dwLowDateTime;
    ftime.HighPart=ft.dwHighDateTime;
    //subtract boot time interval from current time
    ftime.QuadPart = ftime.QuadPart - ticks.QuadPart;
    //Convert ULARGE_INT back to FILETIME
    fout.dwLowDateTime = ftime.LowPart;
    fout.dwHighDateTime = ftime.HighPart;
    printf("FINAL: Filetime lowdatetime %u, highdatetime %u\r\n", fout.dwLowDateTime, fout.dwHighDateTime);
    //Convert FILETIME back to system time
    retval = FileTimeToSystemTime(&fout, &final);
    printf("Return value is %d\r\n", retval);
    printf("Current time %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", current.wYear, current.wMonth, current.wDay,  current.wHour, current.wMinute, current.wSecond);
    printf("Return time %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", final.wYear, final.wMonth, final.wDay,  final.wHour, final.wMinute, final.wSecond);
    return 0;
}

【问题讨论】:

    标签: winapi systemtime filetime


    【解决方案1】:

    我运行它发现它在使用GetLocalTime 时可以正常工作,而不是使用以UTC 表示的GetSystemTime。因此,GetSystemTime 不一定与 PC 上的“时钟”匹配是有道理的。

    不过,除此之外,问题可能是对 GetVersionEx 的调用。正如所写,我认为它总是会为所有值返回零。在调用它之前您需要此行:

    osvi.dwOSVersionInfoSize = sizeof( osvi );
    

    否则 dwBuildNumber 将为零,它将调用 GetTickCount,这仅适用于 49 天左右。另一方面,如果是这样的话,我认为你会得到一个差异更大的结果。

    我不完全确定(如所写)检查是选择调用哪个滴答计数函数所必需的。如果 GetTickCount64 不存在,则应用程序将由于缺少入口点而无法加载(除非可能使用了延迟加载......在这种情况下我不确定)。我相信有必要使用 LoadLibrary 和 GetProcAddress 在这两个函数之间动态做出决定,并让它在旧平台上运行。

    【讨论】:

    • 对不起,我没有弄清楚这一点,我打算在 vista 系统或更高版本(内部版本号> = 6000)上运行 GetTickCount64 并在 xp、2003 等上打开 GetTickCount ......但是当你解释说,我错误地实现了该功能,我需要使用 LoadLibraryEx。尽管如此,在我的系统上,“网络统计工作站”返回“统计自 2011 年 3 月 18 日下午 1:40:58 以来的统计数据”和此代码:“返回时间 2011-03-18 18:01:23”
    • 可能是因为系统是虚拟化的(KVM 来宾),我得到了这种差异?
    • @user86294:我在几台机器上运行它(vmware 映像和 3 个物理机器,包括 32 位、64 位、win7、xp ...)。它在所有情况下都能正常工作。您是否在重新启动时“知道”的机器上运行它?我不太熟悉“网络统计”以及是否“保证”显示启动时间。
    • 我记不太清了,但我也使用事件日志进行了检查。在事件日志中,重新启动时间戳为 2011-03-18 9:40:39,考虑到我的时区 (EDT) 非常接近“网络统计工作站”显示的内容。我想我要重新启动它,尝试在更多的机器上运行代码,然后回复你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 2017-05-12
    相关资源
    最近更新 更多