通过代码在 Windows 操作系统上启用和禁用 DST
Posted
技术标签:
【中文标题】通过代码在 Windows 操作系统上启用和禁用 DST【英文标题】:Enable and disable DST on Windows OS by code 【发布时间】:2019-09-01 19:03:17 【问题描述】:有没有办法(夏令时)?
我一直在按照下一个link 中提到的步骤进行操作,但没有成功...
我也一直在尝试更改 DYNAMIC_TIME_ZONE_INFORMATION
结构的“Bias”属性,它允许我更改日期时间,但不能启用或禁用 DST...
有没有办法解决这个问题?
下一个源码只禁用夏令时,不过我需要重新启用...
OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
TOKEN_PRIVILEGES tp;
LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
DYNAMIC_TIME_ZONE_INFORMATION dyTimeZoneInfo;
ZeroMemory(&dyTimeZoneInfo, sizeof(dyTimeZoneInfo));
DWORD tzId = GetDynamicTimeZoneInformation(&dyTimeZoneInfo);
dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
dyTimeZoneInfo.DaylightBias = 0;
dyTimeZoneInfo.StandardDate.wDay = 0;
dyTimeZoneInfo.StandardDate.wDayOfWeek = 0;
dyTimeZoneInfo.StandardDate.wHour = 0;
dyTimeZoneInfo.StandardDate.wMilliseconds = 0;
dyTimeZoneInfo.StandardDate.wMinute = 0;
dyTimeZoneInfo.StandardDate.wMonth = 0;
dyTimeZoneInfo.StandardDate.wSecond = 0;
dyTimeZoneInfo.StandardDate.wYear = 0;
dyTimeZoneInfo.DaylightDate.wDay = 0;
dyTimeZoneInfo.DaylightDate.wDayOfWeek = 0;
dyTimeZoneInfo.DaylightDate.wHour = 0;
dyTimeZoneInfo.DaylightDate.wMilliseconds = 0;
dyTimeZoneInfo.DaylightDate.wMinute = 0;
dyTimeZoneInfo.DaylightDate.wMonth = 0;
dyTimeZoneInfo.DaylightDate.wSecond = 0;
dyTimeZoneInfo.DaylightDate.wYear = 0;
SetDynamicTimeZoneInformation(&dyTimeZoneInfo);
tp.Privileges[0].Attributes = NULL;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
CloseHandle(hToken);
我将不胜感激。
【问题讨论】:
请出示您的代码。 好的,我已经更新了我的帖子 我相信你应该添加一个返回值检查。不知道函数调用成功与否。 @montonero 我一直在检查所有函数,返回值为'1' 您是否按照here 的规定检查了AdjustTokenPrivileges
的结果?
【参考方案1】:
您的原始代码大部分是正确的。我看到的主要问题是:
dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
切换自动 DST 功能,而您的其余代码严格禁用它。而是将其设置为 true。
dyTimeZoneInfo.DynamicDaylightTimeDisabled = TRUE;
要重新启用 DST,您需要恢复 DaylightBias
、DaylightStart
和 StandardStart
字段的原始值。 (不要假设DaylightBias
总是-60,至少有一个是-30。)
最好只恢复整个DYNAMIC_TIME_ZONE_INFORMATION
结构。为此,请使用EnumDynamicTimeZoneInformation
函数遍历系统上的所有时区,并选择TimeZoneKeyName
与当前时区匹配的时区。
最后,您可能需要考虑为什么需要这样做。通常不再需要通过此机制禁用 DST。这是一个遗留功能。整个世界都有适当的时区条目,包括没有 DST 的地区。如果您只是想在自己的应用程序(可能是系统管理应用程序)中模拟操作系统的设置,那很好。但对于大多数其他目的,您不需要操纵此设置。
【讨论】:
我一直在看timezoneapi.h
,它定义了EnumDynamicTimeZoneInformation
。此功能仅在 Windows 7 和 8 上支持。目前,我使用的是 Windows 10 操作系统和 x64 解决方案平台。还有其他枚举时区的函数吗?
它在 Windows 8 及更高版本(包括 Windows 10)上受支持。您可能还需要包括 Windows.h
。 docs.microsoft.com/en-us/windows/desktop/api/timezoneapi/…
嗨@Matt Johnson,我已经包含了Windows.h
,但仍然找不到函数EnumDynamicTimeZoneInformation
...
斯坦格。您使用的是最新的 Windows SDK 吗?
我使用的是 Windows SDK 8.1 版【参考方案2】:
这个源代码解决了我的问题。
HANDLE hToken;
OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
TOKEN_PRIVILEGES tp;
LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
DYNAMIC_TIME_ZONE_INFORMATION dyTimeZoneInfo;
ZeroMemory(&dyTimeZoneInfo, sizeof(dyTimeZoneInfo));
DWORD tzId = GetDynamicTimeZoneInformation(&dyTimeZoneInfo);
dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
if (dyTimeZoneInfo.DynamicDaylightTimeDisabled)
dyTimeZoneInfo.Bias = dyTimeZoneInfo.StandardBias;
else
dyTimeZoneInfo.Bias = dyTimeZoneInfo.DaylightBias;
SetDynamicTimeZoneInformation(&dyTimeZoneInfo);
tp.Privileges[0].Attributes = NULL;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
CloseHandle(hToken);
【讨论】:
小心。您将StandardBias
和DaylightBias
分配给Bias
字段,但文档解释说这些是delta 的。您正在覆盖 Bias
值。请参阅我的答案。以上是关于通过代码在 Windows 操作系统上启用和禁用 DST的主要内容,如果未能解决你的问题,请参考以下文章
安全扫描扫到服务器的SSL存在隐患,建议禁用SSL,启用TLS,这个在WINDOWS和LINUX上,如何操作?