Программно получать время загрузки системы в С++ (windows)
Так просто, вопрос в том, как получить время загрузки системы в Windows с помощью c/С++.
Поиск этого не получил от меня ответа, я только нашел очень хакерский подход, который читает временную метку файла (само собой разумеется, я отказался прочитать это на полпути).
Другой подход, который я нашел, - это действительно чтение журнальных событий Windows? Предположительно, последний раз загрузился.
Кто-нибудь знает, как это сделать (надеюсь, не слишком много уродливых хаков)?
Ответы
Ответ 1
GetTickCount64
"извлекает количество миллисекунд, прошедших с момента запуска системы."
Как только вы знаете, как долго система работает, это просто вопрос вычитания этой продолжительности с текущего времени, чтобы определить, когда она была загружена. Например, используя библиотеку chrono С++ 11 (поддерживаемую Visual С++ 2012):
auto uptime = std::chrono::milliseconds(GetTickCount64());
auto boot_time = std::chrono::system_clock::now() - uptime;
Ответ 2
Вы также можете использовать WMI, чтобы получить точное время загрузки. WMI не для слабонервных, но он даст вам то, что вы ищете.
Данная информация относится к объекту Win32_OperatingSystem
под свойством LastBootUpTime
. Вы можете изучить другие свойства, используя WMI Tools.
![WMI Explorer showing property instance]()
Edit:
Вы также можете получить эту информацию из командной строки, если хотите.
wmic OS Get LastBootUpTime
В качестве примера в С# он будет выглядеть следующим образом (Использование С++ довольно многословно):
static void Main(string[] args)
{
// Create a query for OS objects
SelectQuery query = new SelectQuery("Win32_OperatingSystem", "Status=\"OK\"");
// Initialize an object searcher with this query
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
string dtString;
// Get the resulting collection and loop through it
foreach (ManagementObject envVar in searcher.Get())
dtString = envVar["LastBootUpTime"].ToString();
}
Ответ 3
C++ Boost использовал WMI LastBootUpTime
но в версии 1.54 переключился на проверку журнала системных событий, и, очевидно, по уважительной причине:
Прерывание ABI: изменена функция начальной загрузки в Windows, чтобы использовать время запуска службы EventLog в качестве времени загрузки системы. Ранее использованный LastBootupTime
из WMI был нестабилен с синхронизацией времени и гибернацией и на практике непригоден. Если вам действительно нужно получить поведение до Boost 1.54, определите BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
из командной строки или detail/workaround.hpp.
Посмотрите на boost/interprocess/detail/win32_api.hpp, около строки 2201, реализацию inline bool get_last_bootup_time(std::string &stamp)
функции inline bool get_last_bootup_time(std::string &stamp)
для примера. (Я смотрю на версию 1.60, если вы хотите сопоставить номера строк.)
На всякий случай, если Boost когда-нибудь умрет, и мое указание на Boost не поможет (да, верно), функция, которую вы хотите, в основном - ReadEventLogA
и идентификатор события, который нужно искать ("Event Log Started" согласно комментариям Boost), видимо 6005
.
Ответ 4
Не отдельный ответ, но я реализовал каждый из трех других ответов и у меня есть некоторые наблюдения, которые могут помочь тем, кто пытается выбрать метод.
Использование GetTickCount64
и вычитание из текущего времени
- Самый быстрый метод с тактовой частотой 0,112 мс.
- Не выдает уникальное/непротиворечивое значение при разрешении своих аргументов за 100 нс, поскольку оно зависит от тактов. Все возвращаемые значения находятся в пределах 1/64 секунды друг от друга.
- Требуется Vista или новее. 32-разрядный счетчик XP переносится на ~ 49 дней и не может использоваться для этого подхода, если ваше приложение/библиотека должно поддерживать более старые версии Windows
Использование запроса WMI из LastBootUpTime
области Win32_OperatingSystem
- Потребовалось 84 мс с использованием COM, 202 мс с использованием командной строки
wmic
. -
CIM_DATETIME
согласованное значение в виде строки CIM_DATETIME
- Класс WMI требует Vista или новее.
Чтение журнала событий
- Самый медленный метод, занимающий 229 мс
- Создает согласованное значение в единицах секунд (время Unix)
- Работает на Windows 2000 или новее.
Методы также производили разные временные метки:
- UpTime: 1558758098843 = 2019-05-25 04:21:38 UTC (иногда: 37)
- WMI: 20190524222528.665400-420 = 2019-05-25 05:25:28 UTC
- Журнал событий: 1558693023 = 2019-05-24 10:17:03 UTC
Вывод: метод журнала событий совместим со старыми версиями Windows, выдает согласованную временную метку во времени Unix, которая не зависит от циклов сна/спящего режима, но также является самой медленной. Учитывая, что это вряд ли будет выполнено в цикле, это, вероятно, лучший вариант.