Включение и отключение перехода на летнее время в ОС Windows с помощью кода

#c #c #winapi #registry #dst

#c #c #winapi #реестр #переход на летнее время

Вопрос:

Есть ли какой-либо способ включить и отключить переход на летнее время (летнее время) в ОС Windows с помощью кода?

Я следовал инструкциям, указанным в следующей ссылке, но безуспешно…

Также я пытался изменить свойство структуры «Смещение« DYNAMIC_TIME_ZONE_INFORMATION , это позволяет мне изменять дату и время, но не включать или отключать летнее время…

Есть ли какой-либо способ решить эту проблему?

Следующий исходный код отключает только переход на летнее время, тем не менее, мне нужно снова включить…

     OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, amp;hToken);

    TOKEN_PRIVILEGES tp;
    LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, amp;tp.Privileges[0].Luid);
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken, FALSE, amp;tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);

    DYNAMIC_TIME_ZONE_INFORMATION dyTimeZoneInfo;
    ZeroMemory(amp;dyTimeZoneInfo, sizeof(dyTimeZoneInfo));
    DWORD tzId = GetDynamicTimeZoneInformation(amp;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(amp;dyTimeZoneInfo);

    tp.Privileges[0].Attributes = NULL;
    AdjustTokenPrivileges(hToken, FALSE, amp;tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);

    CloseHandle(hToken);
  

Я буду признателен за любую помощь.

Комментарии:

1. Пожалуйста, покажите свой код.

2. Хорошо, я обновил свой пост

3. Я считаю, что вам следует добавить проверку возвращаемых значений. Вы не знаете, успешны ли вызовы функций или нет.

4. @montonero Я проверял все функции, и возвращаемые значения равны ‘1’

5. Вы проверили результат AdjustTokenPrivileges , как указано здесь ?

Ответ №1:

Ваш исходный код в основном правильный. Основная проблема, которую я вижу, заключается в следующем:

 dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
  

Это отключает функцию автоматического перехода на летнее время, в то время как остальная часть вашего кода строго отключает ее. Вместо этого установите для него значение true.

 dyTimeZoneInfo.DynamicDaylightTimeDisabled = TRUE;
  

Чтобы повторно включить переход на летнее время, вам необходимо восстановить исходные значения DaylightBias полей , DaylightStart , и StandardStart . (Не предполагайте DaylightBias , что всегда -60, есть хотя бы один, который равен -30.)

Лучше всего просто восстановить всю DYNAMIC_TIME_ZONE_INFORMATION структуру. Для этого используйте EnumDynamicTimeZoneInformation функцию для перебора всех часовых поясов в системе и выберите тот, который TimeZoneKeyName соответствует текущему.

Наконец, вы можете подумать, зачем вам вообще нужно это делать. Отключение перехода на летнее время с помощью этого механизма, как правило, больше не требуется. Это устаревшая функция. Существуют соответствующие записи часовых поясов для всего мира, включая области без перехода на летнее время. Если вы просто пытаетесь эмулировать настройки операционной системы в своем собственном приложении (возможно, в приложении для управления системой), тогда все в порядке. Но для большинства других целей вам не нужно манипулировать этим параметром.

Комментарии:

1. Я посмотрел timezoneapi.h , что определяет EnumDynamicTimeZoneInformation . Эта функция поддерживается только в Windows 7 и 8. В настоящее время я использую ОС Windows 10 и платформу решений x64. Существуют ли другие функции для перечисления часовых поясов?

2. Поддерживается в Windows 8 и выше, включая Windows 10. Возможно Windows.h , вам также потребуется включить. learn.microsoft.com/en-us/windows/desktop/api/timezoneapi /…

3. Привет @Matt Johnson, я включил Windows.h , и функция EnumDynamicTimeZoneInformation все еще не найдена…

4. Изменение. Используете ли вы новейший Windows SDK?

5. Я использую Windows SDK версии 8.1

Ответ №2:

Этот исходный код решает мою проблему.

     HANDLE hToken;
    OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, amp;hToken);

    TOKEN_PRIVILEGES tp;
    LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, amp;tp.Privileges[0].Luid);
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken, FALSE, amp;tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);

    DYNAMIC_TIME_ZONE_INFORMATION dyTimeZoneInfo;
    ZeroMemory(amp;dyTimeZoneInfo, sizeof(dyTimeZoneInfo));
    DWORD tzId = GetDynamicTimeZoneInformation(amp;dyTimeZoneInfo);

    dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;

    if (dyTimeZoneInfo.DynamicDaylightTimeDisabled)
        dyTimeZoneInfo.Bias = dyTimeZoneInfo.StandardBias;
    else
        dyTimeZoneInfo.Bias = dyTimeZoneInfo.DaylightBias;

    SetDynamicTimeZoneInformation(amp;dyTimeZoneInfo);

    tp.Privileges[0].Attributes = NULL;
    AdjustTokenPrivileges(hToken, FALSE, amp;tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);

    CloseHandle(hToken);
  

Комментарии:

1. Осторожно. Вы присваиваете полю StandardBias и DaylightBias Bias , но в документах объясняется, что это дельта . Вы перезаписываете Bias значение. Вместо этого смотрите мой ответ.