如何使用 C++(win32/MFC) 跟踪准确的 windows 启动时间

How to track the accurate windows startup time using C++(win32/MFC)

我正在创建一个跟踪系统启动时间的应用程序。 我尝试了 GetTickcount() 方法和 WMI query.In 这两种情况我得到了相同的解决方案。
但是我得到的时间和实际启动时间是不一样的。 通过研究,我发现由于在电源选项中启用了快速启动选项,当我们关闭系统时,系统不会启动。 我需要的是实际启动时间 time.How 我们可以使用 C++ 获取实际启动时间吗?

我关闭了系统并在 20 年 6 月 24 日 8:22:05 上午打开它,但我得到的启动时间是 5:11:05 下午 5:11:05 下午

启用快速启动选项后,单击开始菜单-> 关机将使机器进入睡眠状态mode/hibernation,而不是关机。但重启菜单不受影响。 (并且从命令行关闭也不会像我的测试那样受到影响)。所以,开机时间不会被重置。

您可以尝试以下方法:

  1. 关闭“快速启动”选项。
  2. 在任务计划中添加一个任务来记录系统启动的时间。
  3. 阅读 Windows 事件日志:

事件 ID 27 记录内核启动事件。正如您在图片中看到的,启动类型 0x1 表示这是一个快速启动。您可以阅读最新的并获得创建时间。

示例(参考本示例文档:Querying for Events):

#include <windows.h>
#include <sddl.h>
#include <stdio.h>
#include <winevt.h>

#pragma comment(lib, "wevtapi.lib")

#define ARRAY_SIZE 1
#define TIMEOUT 1000  // 1 second; Set and use in place of INFINITE in EvtNext call

DWORD PrintResults(EVT_HANDLE hResults);
DWORD PrintEvent(EVT_HANDLE hEvent); // Shown in the Rendering Events topic

void main(void)
{
    DWORD status = ERROR_SUCCESS;
    EVT_HANDLE hResults = NULL;
    LPCWSTR pwsPath = L"System";
    LPCWSTR pwsQuery = L"Event/System[EventID=27]";

    hResults = EvtQuery(NULL, pwsPath, pwsQuery, EvtQueryChannelPath | EvtQueryReverseDirection);
    if (NULL == hResults)
    {
        status = GetLastError();

        if (ERROR_EVT_CHANNEL_NOT_FOUND == status)
            wprintf(L"The channel was not found.\n");
        else if (ERROR_EVT_INVALID_QUERY == status)
            // You can call the EvtGetExtendedStatus function to try to get 
            // additional information as to what is wrong with the query.
            wprintf(L"The query is not valid.\n");
        else
            wprintf(L"EvtQuery failed with %lu.\n", status);

        goto cleanup;
    }

    PrintResults(hResults);

cleanup:

    if (hResults)
        EvtClose(hResults);

}
// Enumerate all the events in the result set. 
DWORD PrintResults(EVT_HANDLE hResults)
{
    DWORD status = ERROR_SUCCESS;
    EVT_HANDLE hEvents[ARRAY_SIZE];
    DWORD dwReturned = 0;

    // Get a block of events from the result set.
    if (!EvtNext(hResults, ARRAY_SIZE, hEvents, INFINITE, 0, &dwReturned))
    {
        if (ERROR_NO_MORE_ITEMS != (status = GetLastError()))
        {
            wprintf(L"EvtNext failed with %lu\n", status);
        }

        goto cleanup;
    }

    // For each event, call the PrintEvent function which renders the
    // event for display. PrintEvent is shown in RenderingEvents.
    /*for (DWORD i = 0; i < dwReturned; i++)
    {
        if (ERROR_SUCCESS == (status = PrintEvent(hEvents[i])))
        {
            EvtClose(hEvents[i]);
            hEvents[i] = NULL;
        }
        else
        {
            goto cleanup;
        }
    }*/
    if (ERROR_SUCCESS == (status = PrintEvent(hEvents[0])))
    {
        EvtClose(hEvents[0]);
        hEvents[0] = NULL;
    }
    else
    {
        goto cleanup;
    }


cleanup:

    for (DWORD i = 0; i < dwReturned; i++)
    {
        if (NULL != hEvents[i])
            EvtClose(hEvents[i]);
    }

    return status;
}
DWORD PrintEvent(EVT_HANDLE hEvent)
{
    DWORD status = ERROR_SUCCESS;
    DWORD dwBufferSize = 0;
    DWORD dwBufferUsed = 0;
    DWORD dwPropertyCount = 0;
    LPWSTR pRenderedContent = NULL;

    if (!EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount))
    {
        if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
        {
            dwBufferSize = dwBufferUsed;
            pRenderedContent = (LPWSTR)malloc(dwBufferSize);
            if (pRenderedContent)
            {
                EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount);
            }
            else
            {
                wprintf(L"malloc failed\n");
                status = ERROR_OUTOFMEMORY;
                goto cleanup;
            }
        }

        if (ERROR_SUCCESS != (status = GetLastError()))
        {
            wprintf(L"EvtRender failed with %d\n", status);
            goto cleanup;
        }
    }

    wprintf(L"%s\n\n", pRenderedContent);

cleanup:

    if (pRenderedContent)
        free(pRenderedContent);

    return status;
}

结果: