2

現在の時刻の 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;
}
4

1 に答える 1

2

GetLocalTime実行したところ、UTC で表される GetSystemTime とは対照的に、使用すると正しく動作することがわかりました。したがって、GetSystemTime が必ずしも PC の「時計」と一致するとは限りません。

ただし、それ以外に、問題は GetVersionEx の呼び出しである可能性があります。書かれているように、すべての値に対して常にゼロを返すと思います。呼び出す前に、次の行が必要です。

osvi.dwOSVersionInfoSize = sizeof( osvi );

それ以外の場合、dwBuildNumber はゼロになり、GetTickCount が呼び出されますが、これは 49 日間しか有効ではありません。逆に言えば、もっと差のある結果になると思います。

(書かれているように)どのティックカウント関数を呼び出すかを選択するためにチェックが必要かどうかは完全にはわかりません。GetTickCount64 が存在しない場合、エントリポイントが見つからないため、アプリは読み込まれません (遅延読み込みが使用された場合を除きます...その場合はわかりません)。LoadLibrary と GetProcAddress を使用して、これら 2 つの関数を動的に決定し、古いプラットフォームで動作させる必要があると思います。

于 2011-03-23T21:27:48.427 に答える