Windows10中调用SetSystemTime()设置系统时间失败(错误1314)
解决Windows 10下GPS同步系统时间失败(错误码1314)
问题背景
开发程序通过GPS时间同步Windows系统时间,已将GPS时间转换为SYSTEMTIME结构体,但调用SetSystemTime失败,返回错误码1314(客户端缺少所需特权),手动修改系统时间后问题依旧。
代码中的核心问题
- 未获取进程令牌:
HANDLE hToken未初始化,也未调用OpenProcessToken获取当前进程的访问令牌,导致AdjustTokenPrivileges无法正确启用修改系统时间的特权。 - 临时对象地址无效:
&convertDateTimeToSystemTime(gpsTime)取的是函数返回的临时对象地址,临时对象在语句执行后立即销毁,导致SetSystemTime传入无效指针。 - 特权调整判断错误:仅用
GetLastError() == NO_ERROR判断AdjustTokenPrivileges是否成功,忽略了特权已启用时返回的ERROR_NOT_ALL_ASSIGNED(此情况属于操作成功)。
修复后的代码
特权配置与时间设置逻辑
// 打开当前进程的访问令牌 HANDLE hToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { std::stringstream logStream; logStream << "Failed to open process token, error code: " << GetLastError(); std::cout << logStream.str() << std::endl; return; } // 配置SE_SYSTEMTIME_NAME特权 TOKEN_PRIVILEGES tkp; LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; BOOL privSuccess = AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); DWORD privErr = GetLastError(); // 特权调整成功的判断:函数返回非0,且错误为NO_ERROR或ERROR_NOT_ALL_ASSIGNED(特权已启用) if (privSuccess && (privErr == NO_ERROR || privErr == ERROR_NOT_ALL_ASSIGNED)) { // 先获取转换后的SYSTEMTIME对象,避免临时对象地址失效 SYSTEMTIME sysTime = convertDateTimeToSystemTime(gpsTime); // 注意:SetSystemTime要求传入UTC时间,确认GPS时间是否为UTC格式 if (SetSystemTime(&sysTime)) { std::stringstream logStream; logStream << "Successfully updated system time to: " << timeString; std::cout << logStream.str() << std::endl; } else { std::stringstream logStream; logStream << "Failed to update system time, error code: " << GetLastError(); std::cout << logStream.str() << std::endl; } } else { std::stringstream logStream; logStream << "Failed to adjust token privileges, error code: " << privErr; std::cout << logStream.str() << std::endl; } // 关闭令牌句柄,释放资源 CloseHandle(hToken);
时间转换函数(补充说明)
SYSTEMTIME GpsMessageProcessor::convertDateTimeToSystemTime(const Poco::DateTime time) { SYSTEMTIME convertedTime; convertedTime.wYear = time.year(); convertedTime.wMonth = time.month(); convertedTime.wDay = time.day(); convertedTime.wHour = time.hour(); convertedTime.wMinute = time.minute(); convertedTime.wSecond = time.second(); convertedTime.wMilliseconds = time.millisecond(); // 重要提示:SetSystemTime接收UTC时间,如果GPS输出的是本地时间,必须先转换为UTC // 若需要时区转换,可使用SystemTimeToTzSpecificLocalTime或相关API实现 return convertedTime; }
额外注意事项
- 管理员权限:程序必须以管理员身份运行,否则无法获取修改系统时间的权限。
- UTC时间校验:确保传入
SetSystemTime的是UTC时间,否则系统时间会出现偏差。 - 资源释放:使用完进程令牌后必须调用
CloseHandle关闭,避免资源泄漏。
内容的提问来源于stack exchange,提问作者EraticMagician
相关产品推荐
相关产品推荐

