Есть ли надежный способ обработки часовых поясов, когда приложения.NET используются с XenApp?

Я столкнулся с проблемой, связанной с идентификаторами часовых поясов.NET в сочетании с XenApp, которая может быть уменьшена до следующего фрагмента TimeZoneNotFoundException (т.е. призыв к TimeZoneInfo.FindSystemTimeZoneById):

var tzLocal = TimeZoneInfo.Local;
var tzId = tzLocal.Id;
var tz = TimeZoneInfo.FindSystemTimeZoneById(tzId);

Точный текст исключения:

System.TimeZoneNotFoundException:
The time zone ID 'Mitteleuropäische Zeit' was not found on the local computer.
  at System.TimeZoneInfo.GetTimeZone(String id)
  at System.TimeZoneInfo.FindSystemTimeZoneById(String id)

(Нечто подобное происходит в NodaTime 1.1, например, внутри вызова NodaTime.DateTimeZoneProviders.Bcl.GetSystemDefault()).

Странно то, что TimeZoneInfo.Local.Id похоже, возвращает немецкое имя часового пояса, хотя сервер работает с языком, установленным на английский, и идентификатор часового пояса должен быть независимым от языка (см. ID.Net TimeZoneInfo - это зависит от языка Windows?). Но язык клиента - немецкий... (Обновление / уточнение: проблема не возникнет, если клиент и сервер используют один и тот же язык.)

Я думаю, что здесь происходит:

  1. .NET звонки GetTimeZoneInformation в kernel32.dll для получения местного часового пояса.
  2. Вызов API перехватывается XenApp (см. Возможно ли получить часовой пояс пользователя для приложения, размещенного в Citrix XenApp?), Поскольку XenApp можно настроить на использование локального часового пояса клиента (см. http://mdaslam.wordpress.com/2010/01/05/xenapp-time-zone-setting/).
  3. Результирующий TIME_ZONE_INFORMATION структура содержит стандартное немецкое имя (я проверил это с помощью p/invoke на английском сервере XenApp).
  4. Так как TIME_ZONE_INFORMATION структура (см. http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx) не содержит независимого от языка идентификатора часового пояса.NET не соответствует возвращенному Немецкий идентификатор часового пояса к его локальной базе данных часовых поясов (с английскими именами) и использует (локализованное) стандартное имя в качестве запасного идентификатора для часового пояса. Ergo TimeZoneInfo.Local.Id содержит немецкое название "местного" часового пояса.
  5. затем TimeZoneInfo.FindSystemTimeZoneById происходит сбой для этого резервного идентификатора, потому что он действительно неизвестен системе (потому что это локализованное стандартное имя из системы с другим языком).

Итак, как я могу обойти эту проблему, кроме как сказать клиенту отключить использование часового пояса клиента в XenApp?

1 ответ

Это всего лишь предположение, но, вероятно, когда XenApp отображает часовой пояс клиента, он использует GetTimeZoneInformation функция из Win32 API. Это возвращает TIME_ZONE_INFORMATION структура, которая не включает в себя идентификатор часового пояса. Он возвращает только информацию о часовом поясе, такую ​​как смещение и текущая информация о летнем времени, вместе с локализованными именами.

Вероятно, вместо этого следует использовать GetDynamicTimeZoneInformation, который возвращает DYNAMIC_TIME_ZONE_INFORMATION состав. Одним из элементов которого является TimeZoneKeyName, который будет сопоставлен с.NET TimeZoneInfo.Id без локализации.

Теперь я очень мало знаю о XenApp, но вполне возможно, что Citrix уже знает об этой проблеме и либо исправил ее в последней версии, либо работает над ней. Если возможно, вы должны обновиться до последней версии, и если она все еще не работает, то посмотрите, есть ли она в их списке ошибок. Если нет, то сообщите об этом и сделайте ссылку на этот пост.

Другие вопросы по тегам