Время непрерывной работы (Uptime) Windows

Для получения времени непрерывной работы системы обычно используется функция API GetTickCount. Она возвращает количество миллисекунд, прошедших с момента последнего старта системы. Проблема в том, что счетчик имеет тип dword, и по прошествии примерно 50 дней (49,7 если быть точным) достигает предельного значения и обнуляется. Конечно, продержать систему без перезагрузки почти два месяца трудно, но не значит что невозможно. Поэтому для получения гарантированно точного времени работы системы воспользуемся функцией NtQuerySystemInformation. Достаточно долго эта функция относилась к разряду недокументированных, теперь же на MSDN по ней имеется описание с примечанием, что ее использование в прикладных программах все равно нежелательно.
; Сегмент данных
section '.data' data readable writeable
 
; По умолчанию структура в FASM не определена, сделаем это самостоятельно
; Для получения необходимой информации нужны только два первых значения
struct SYSTEM_TIME_INFORMATION
       liKeBootTime       dq ?  ; Время старта системы
       liKeSystemTime     dq ?  ; Текущее время
       liExpTimeZoneBias  dq ?
       uCurrentTimeZoneId dd ?
       dwReserved         dw ?
ends
 
SystemTime   SYSTEM_TIME_INFORMATION  ; Наша структура с данными
 
; Константа нужного класса информации тоже не определена, сделаем это сами
GET_SYSTEM_TIME_INFORMATION = 3 
 
; Сегмент кода
section '.code' code readable executable
...
        invoke  NtQuerySystemInformation, GET_SYSTEM_TIME_INFORMATION,\
                SystemTime, sizeof.SYSTEM_TIME_INFORMATION, 0
        ; Записать в регистры EDX:EAX текущее время в миллисекундах
        mov     eax, dword [SystemTime.liKeSystemTime]
        mov     edx, dword [SystemTime.liKeSystemTime+4]
        ; Вычесть время старта системы
        sub     eax, dword [SystemTime.liKeBootTime]
        sbb     edx, dword [SystemTime.liKeBootTime+4]
        ; Теперь в регистры EDX:EAX записано реальное количество миллисекунд,
        ; прошедшее с момента старта системы
...

Преобразовать миллисекунды в обычный вид даты и времени можно при помощи пары стандартных функций FileTimeToLocalFileTime и FileTimeToSystemTime.
; Сегмент данных
section '.data' data readable writeable
 
; По умолчанию структура в FASM не определена, сделаем это самостоятельно
; Для получения необходимой информации нужны только два первых значения
struct SYSTEM_TIME_INFORMATION
       liKeBootTime       dq ?  ; Время старта системы
       liKeSystemTime     dq ?  ; Текущее время
       liExpTimeZoneBias  dq ?
       uCurrentTimeZoneId dd ?
       dwReserved         dw ?
ends
 
SystemTime   SYSTEM_TIME_INFORMATION  ; Наша структура с данными
 
; Добавляются две стандартные структуры для работы с датой и временем
ftSystemTime FILETIME
stSystemTime SYSTEMTIME
 
; Константа нужного класса информации тоже не определена, сделаем это сами
GET_SYSTEM_TIME_INFORMATION = 3 
 
; Сегмент кода
section '.code' code readable executable
...
        invoke  NtQuerySystemInformation, GET_SYSTEM_TIME_INFORMATION,\
                SystemTime, sizeof.SYSTEM_TIME_INFORMATION, 0
        ; Получить текущее системное время. Для получения времени старта
        ; системы замените в вызове SystemTime.liKeSystemTime на
        ; SystemTime.liKeBootTime
        invoke  FileTimeToLocalFileTime, SystemTime.liKeSystemTime,\
                ftSystemTime
        ; Преобразовать в системный формат даты и времени
        invoke  FileTimeToSystemTime, ftSystemTime, stSystemTime
 
        ; Теперь к элементам структуры stSystemTime можно обращаться
        ; обычными способами: [stSystemTime.wDay], [stSystemTime.wMonth] и т.д.
...

После выполнения этого кода структура stSystemTime (стандартная структура SYSTEMTIME) содержит все значения в удобном для доступа и обработки виде.
Теги:
Uptime, Время непрерывной работы
Добавлено: 10 Апреля 2018 08:32:20 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...