如何在C++中获取Windows系统的启动时间?
获取Windows系统启动时间的C++实现方法
首先澄清:GetTickCount64()返回的是系统启动后经过的毫秒数,并非你的exe程序启动时间。如果要得到具体的系统启动日期时间,有以下几种可靠方法:
方法1:通过当前时间反推启动时间
利用系统运行时长和当前时间计算启动时间,步骤简单且兼容性好:
- 获取当前高精度系统时间(
FILETIME格式) - 用
GetTickCount64()获取系统启动后经过的毫秒数 - 将毫秒数转换为
FILETIME的最小单位(100纳秒),从当前时间中减去该值得到启动时间
代码示例:
#include <windows.h> #include <iostream> #include <iomanip> void GetSystemBootTime(FILETIME* bootTime) { FILETIME currentTime; GetSystemTimePreciseAsFileTime(¤tTime); // 获取高精度当前时间 // 转换FILETIME为ULONGLONG便于计算 ULONGLONG currentTimeLL = ((ULONGLONG)currentTime.dwHighDateTime << 32) | currentTime.dwLowDateTime; ULONGLONG elapsedMs = GetTickCount64(); // 毫秒转100纳秒单位(1ms = 10000 * 100ns) ULONGLONG elapsed100Ns = elapsedMs * 10000; // 计算启动时间并写回FILETIME结构 ULONGLONG bootTimeLL = currentTimeLL - elapsed100Ns; bootTime->dwHighDateTime = (DWORD)(bootTimeLL >> 32); bootTime->dwLowDateTime = (DWORD)(bootTimeLL & 0xFFFFFFFF); } int main() { FILETIME bootTime; GetSystemBootTime(&bootTime); // 转换为UTC时间输出 SYSTEMTIME st; FileTimeToSystemTime(&bootTime, &st); std::cout << "系统启动时间(UTC):" << std::setw(4) << st.wYear << "-" << std::setw(2) << std::setfill('0') << st.wMonth << "-" << std::setw(2) << st.wDay << " " << std::setw(2) << st.wHour << ":" << std::setw(2) << st.wMinute << ":" << std::setw(2) << st.wSecond << std::endl; // 转换为本地时间输出 FileTimeToLocalFileTime(&bootTime, &bootTime); FileTimeToSystemTime(&bootTime, &st); std::cout << "系统启动时间(本地):" << std::setw(4) << st.wYear << "-" << std::setw(2) << std::setfill('0') << st.wMonth << "-" << std::setw(2) << st.wDay << " " << std::setw(2) << st.wHour << ":" << std::setw(2) << st.wMinute << ":" << std::setw(2) << st.wSecond << std::endl; return 0; }
方法2:使用原生API直接查询
通过NtQuerySystemInformation直接获取系统启动时间,效率更高,需要链接ntdll.lib:
#include <windows.h> #include <winternl.h> #include <iostream> #include <iomanip> #pragma comment(lib, "ntdll.lib") typedef struct _SYSTEM_BOOT_INFORMATION { LARGE_INTEGER BootTime; } SYSTEM_BOOT_INFORMATION, *PSYSTEM_BOOT_INFORMATION; int main() { SYSTEM_BOOT_INFORMATION bootInfo; NTSTATUS status = NtQuerySystemInformation(SystemBootInformation, &bootInfo, sizeof(bootInfo), nullptr); if (NT_SUCCESS(status)) { FILETIME bootTime; bootTime.dwHighDateTime = bootInfo.BootTime.HighPart; bootTime.dwLowDateTime = bootInfo.BootTime.LowPart; // 转换为本地时间输出 SYSTEMTIME st; FileTimeToLocalFileTime(&bootTime, &bootTime); FileTimeToSystemTime(&bootTime, &st); std::cout << "系统启动时间(本地):" << std::setw(4) << st.wYear << "-" << std::setw(2) << std::setfill('0') << st.wMonth << "-" << std::setw(2) << st.wDay << " " << std::setw(2) << st.wHour << ":" << std::setw(2) << st.wMinute << ":" << std::setw(2) << st.wSecond << std::endl; } else { std::cerr << "获取启动时间失败,错误码:" << status << std::endl; } return 0; }
方法3:通过WMI查询(适合多系统信息场景)
如果需要同时获取其他系统属性,可以通过WMI查询Win32_OperatingSystem类的LastBootUpTime属性,需要链接wbemuuid.lib:
#include <windows.h> #include <wbemidl.h> #include <iostream> #include <iomanip> #pragma comment(lib, "wbemuuid.lib") int main() { HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); if (FAILED(hr)) { std::cerr << "COM初始化失败,错误码:" << hr << std::endl; return 1; } hr = CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE, nullptr); if (FAILED(hr)) { std::cerr << "安全初始化失败,错误码:" << hr << std::endl; CoUninitialize(); return 1; } IWbemLocator* pLoc = nullptr; hr = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); if (FAILED(hr)) { std::cerr << "创建WbemLocator失败,错误码:" << hr << std::endl; CoUninitialize(); return 1; } IWbemServices* pSvc = nullptr; hr = pLoc->ConnectServer(L"ROOT\\CIMV2", nullptr, nullptr, nullptr, 0, nullptr, nullptr, &pSvc); if (FAILED(hr)) { std::cerr << "连接WMI服务失败,错误码:" << hr << std::endl; pLoc->Release(); CoUninitialize(); return 1; } hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE); if (FAILED(hr)) { std::cerr << "设置代理失败,错误码:" << hr << std::endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; } IEnumWbemClassObject* pEnumerator = nullptr; hr = pSvc->ExecQuery(L"WQL", L"SELECT LastBootUpTime FROM Win32_OperatingSystem", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &pEnumerator); if (FAILED(hr)) { std::cerr << "执行查询失败,错误码:" << hr << std::endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; } IWbemClassObject* pclsObj = nullptr; ULONG uReturn = 0; while (pEnumerator) { hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (uReturn == 0) break; VARIANT vtProp; hr = pclsObj->Get(L"LastBootUpTime", 0, &vtProp, nullptr, nullptr); if (SUCCEEDED(hr)) { // 解析WMI时间格式(YYYYMMDDHHMMSS.ffffff+UUU) SYSTEMTIME st; if (swscanf_s(vtProp.bstrVal, L"%4hu%2hu%2hu%2hu%2hu%2hu", &st.wYear, &st.wMonth, &st.wDay, &st.wHour, &st.wMinute, &st.wSecond) == 6) { st.wMilliseconds = 0; std::cout << "系统启动时间(本地):" << std::setw(4) << st.wYear << "-" << std::setw(2) << std::setfill('0') << st.wMonth << "-" << std::setw(2) << st.wDay << " " << std::setw(2) << st.wHour << ":" << std::setw(2) << st.wMinute << ":" << std::setw(2) << st.wSecond << std::endl; } VariantClear(&vtProp); } pclsObj->Release(); } pEnumerator->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; }
注意事项
GetTickCount64()不受系统时间调整影响,适合计算相对时长;若需绝对时间,优先选方法1或2- 方法2的原生API效率最高,支持Windows XP及以上系统
- WMI方法功能全面但开销较大,适合需要批量获取系统信息的场景
内容的提问来源于stack exchange,提问作者vrajeshirke
相关产品推荐
相关产品推荐

