GetProcessTimes 返回的 CreateTime 是 Windows FILETIME 格式(100纳秒精度,自1601-01-01 UTC起),需用 FileTimeToSystemTime 转换为可读时间;其值精确记录内核创建时刻,不受系统时间调整影响,但实际分辨率受限于系统时钟精度(通常10–15ms)。

GetProcessTimes 返回的 CreateTime 是进程启动时间,但需注意时钟基准
GetProcessTimes 确实能拿到进程创建时间,但它返回的是 Windows FILETIME(100纳秒精度,自 1601-01-01 UTC 起),不是 Unix 时间戳或本地时间。直接打印 CreateTime 的低/高 DWORD 会得到一串无意义数字。
常见错误是把 CreateTime 当作毫秒时间戳用,或者误以为它和 GetSystemTimeAsFileTime 返回值可直接相减比较——其实可以,但必须用 FileTimeToSystemTime 或 FileTimeToLocalFileTime 转换后才便于人类阅读。
- 必须先调用
OpenProcess获取当前进程句柄(GetCurrentProcess()更安全,权限足够) -
CreateTime是内核记录的精确创建时刻,不受系统时间调整影响(如手动改系统时间、NTP 同步) - 多线程环境下,该时间点对应的是
CreateProcess返回前的内核调度时刻,比main函数第一行执行早几微秒到毫秒不等
用 FileTimeToSystemTime 把 CreateTime 转成可读时间
FILETIME 不是结构体,不能直接访问年月日字段;必须经转换才能输出。别用 CTime 或 std::chrono::file_clock(C++20 前不支持 FILETIME 直接构造)。
正确做法是:声明 SYSTEMTIME st = {},再调用 FileTimeToSystemTime(&ftCreate, &st)。失败时检查 GetLastError(),常见原因是传入了非法 FILETIME(如全零)。
立即学习“C++免费学习笔记(深入)”;
- 转换后
st.wYear到st.wMilliseconds就是标准的年月日时分秒毫秒 - 注意
SYSTEMTIME是本地时区时间,若需 UTC 时间,先用FileTimeToUniversalTime(Windows 10 1809+)或手动减去时区偏移 - 如果只要时间戳用于计算(比如判断进程运行了多久),可跳过转换,直接用
ULARGE_INTEGER对CreateTime和当前GetSystemTimeAsFileTime做差,再除以 10000 得到毫秒
获取当前进程启动时间的最小可行代码片段
#include <windows.h>
#include <iostream>
int main() {
HANDLE hProc = GetCurrentProcess();
FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (GetProcessTimes(hProc, &ftCreate, &ftExit, &ftKernel, &ftUser)) {
SYSTEMTIME st = {};
if (FileTimeToSystemTime(&ftCreate, &st)) {
std::cout << "Started: "
<< st.wYear << "-" << st.wMonth << "-" << st.wDay << " "
<< st.wHour << ":" << st.wMinute << ":" << st.wSecond << "."
<< st.wMilliseconds << "\n";
}
}
return 0;
}
这段代码在 VS2019+ / MinGW-w64 下都能编译通过。关键点:GetCurrentProcess() 不需要额外权限,比 OpenProcess(PROCESS_QUERY_INFORMATION, ...) 更简洁可靠;ftExit 对当前进程永远为 0(除非已退出),不用处理。
- 链接时不需要额外库,
kernel32.lib默认已链入 - 如果程序被调试器启动(如 VS F5),
CreateTime仍是目标进程自身的创建时间,不是调试器启动时间 - 沙盒环境(如 Windows AppContainer)可能拒绝返回
GetProcessTimes,此时GetLastError()返回ERROR_ACCESS_DENIED
替代方案:读取 \Process\ID\StartTime 性能计数器?不推荐
有人尝试用 PdhOpenQuery + PdhAddCounter 查询 \Process(*)\Start Time,这条路理论上可行,但实际踩坑多:
- 性能计数器名称依赖系统语言(英文系统是
Start Time,中文可能是启动时间) - 必须提前初始化 PDH(
PdhOpenQuery),且每轮查询要调用PdhCollectQueryData+PdhGetFormattedCounterValue,延迟高、开销大 - 对当前进程 ID 的计数器可能尚未注册(尤其刚启动时),首次调用常返回
PDH_INVALID_DATA -
GetProcessTimes是内核原生接口,零额外依赖、无语言适配问题、毫秒级响应
除非你在写一个跨平台监控工具并已封装好 PDH 层,否则没必要绕远路。Windows 下查自己进程启动时间,GetProcessTimes 就是最直接、最稳定的选择。
真正容易被忽略的是:FILETIME 的 100 纳秒单位和 Windows 系统时钟精度(通常 10–15ms)并不匹配——CreateTime 理论上精确,但实际分辨率受限于系统时钟中断频率。别指望靠它做微秒级启动时序分析。


















