【问题标题】:Enable and disable DST on Windows OS by code通过代码在 Windows 操作系统上启用和禁用 DST
【发布时间】:2019-09-01 19:03:17
【问题描述】:

有没有办法通过代码在 Windows 操作系统上启用和禁用 DST(夏令时)?

我一直在按照下一个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 的结果?

标签: c++ c winapi registry dst


【解决方案1】:

您的原始代码大部分是正确的。我看到的主要问题是:

dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;

切换自动 DST 功能,而您的其余代码严格禁用它。而是将其设置为 true。

dyTimeZoneInfo.DynamicDaylightTimeDisabled = TRUE;

要重新启用 DST,您需要恢复 DaylightBiasDaylightStartStandardStart 字段的原始值。 (不要假设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.hdocs.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);

【讨论】:

  • 小心。您将StandardBiasDaylightBias 分配给Bias 字段,但文档解释说这些是delta 的。您正在覆盖 Bias 值。请参阅我的答案。
猜你喜欢
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 2011-01-15
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多