1

WMIを使用して最後の起動時間を取得するのではなく、とを使用して計算したかったの::GetSystemTime()です::GetTickCount64。しかし、ミリ秒に達すると、FILETIMEオブジェクトに戻る方法がわかりません。

私はこれを試しました:

static ULONGLONG FileTimeToMillis(const FILETIME &ft)
{
    ULARGE_INTEGER uli;
    uli.LowPart = ft.dwLowDateTime; // could use memcpy here!
    uli.HighPart = ft.dwHighDateTime;

    return uli.QuadPart/10000;
}

static void MillisToSystemTime(ULONGLONG millis, SYSTEMTIME *st)
{
   UINT64 t = static_cast<UINT64>(-10000) * static_cast<UINT64>(millis);

   FILETIME ft;
   ft.dwLowDateTime = static_cast<DWORD(t & 0xFFFFFFFF);
   ft.dwHighDateTime = static_cast<DWORD>(t >> 32);

   ::FileTimeToSystemTime(&ft, st);
}

void main()
{
    SYSTEMTIME st, lt, st2, lt2;

    ::GetSystemTime(&st);
    ::GetLocalTime(&lt);

    cout << "The system time is: " << st.wHour << ":" << st.wMinute << ":" << st.wSecond << endl;
    cout << "The local time is: "  << lt.wHour << ":" << lt.wMinute << ":" << lt.wSecond << endl;

    FILETIME sft, lft;
    ::SystemTimeToFileTime(&st, &sft);
    ::SystemTimeToFileTime(&lt, &lft);  

    cout << "The system time in millis is: " << FileTimeToMillis(sft) << endl;
    cout << "The local time in millis is: "  << FileTimeToMillis(lft) << endl;

    MillisToSystemTime(FileTimeToMillis(sft), &st2);
    MillisToSystemTime(FileTimeToMillis(sft), &lt2);

    cout << "The system time (post conversion) is: " << st2.wHour << ":" << st2.wMinute << ":" << st2.wSecond << endl;
    cout << "The local time (post conversion) is: "  << lt2.wHour << ":" << lt2.wMinute << ":" << lt2.wSecond << endl;
}

しかし、私は確かに期待されたものを得ることができません。代わりに、次のようになります。

The system time is: 15:5:2
The local time is: 10:5:2
The system time in millis is: 12984678302935
The local time in millis is: 12984660302935
The system time (post conversion) is: 52428:52428:52428
The local time (post conversion) is: 52428:52428:52428

何か案は?Boostを使用するように、またはBoostを使用できないために、私に言わないでください。

4

2 に答える 2

4

システム時間(変換後)は次のとおりです:52428:52428:52428

変な値を取得するときは、常に最初に16進数に変換してください。52428==0xcccc。これは、デバッグビルドで生成されたコードが変数を初期化するために使用する値です。したがって、初期化されていないメモリを見ています。

次の防御戦略は、WindowsAPI関数の戻り値を決して無視しないことです。MFCで使用可能なもののようなVERIFY()マクロを使用します。そうすれば、FileTimeToSystemTime()が失敗することが簡単にわかります。

バグは-10000です。

于 2012-06-20T15:40:40.010 に答える
3

算術演算を間違って行っていたことがわかりました。とを読んでみるULARGE_INTEGERと、ビットシフトやキャストの混乱を避けながら、のをFILETIME直接操作して、高低のピースを正しく引き出すことができることがわかりました。QuadPartULARGE_INTEGER

static UINT64 FileTimeToMillis(const FILETIME &ft)
{
    ULARGE_INTEGER uli;
    uli.LowPart = ft.dwLowDateTime; // could use memcpy here!
    uli.HighPart = ft.dwHighDateTime;

    return static_cast<UINT64>(uli.QuadPart/10000);
}

static void MillisToSystemTime(UINT64 millis, SYSTEMTIME *st)
{
    UINT64 multiplier = 10000;
    UINT64 t = multiplier * millis;

    ULARGE_INTEGER li;
    li.QuadPart = t;
    // NOTE, DON'T have to do this any longer because we're putting
    // in the 64bit UINT directly
    //li.LowPart = static_cast<DWORD>(t & 0xFFFFFFFF);
    //li.HighPart = static_cast<DWORD>(t >> 32);

    FILETIME ft;
    ft.dwLowDateTime = li.LowPart;
    ft.dwHighDateTime = li.HighPart;

    ::FileTimeToSystemTime(&ft, st);
}

キーはMSDNから以下を読んでいました:

相対時間を取得するために、FILETIME構造体に値を加算および減算することはお勧めしません。代わりに、ファイル時間の下位部分と上位部分をULARGE_INTEGER構造体にコピーし、QuadPartメンバーで64ビット演算を実行し、LowPartメンバーとHighPartメンバーをFILETIME構造体にコピーする必要があります。

于 2012-06-20T15:38:22.103 に答える