2

我遇到了一个与 .NET 时区 ID 结合 XenApp 相关的问题,可以简化为以下代码段,抛出 a 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 ID - Is it Windows Language Specific?)。但是客户端的语言是德语......(更新/澄清:如果客户端和服务器使用相同的语言,则不会出现问题。)

我认为这里发生的是:

  1. .NET 调用GetTimeZoneInformationkernel32.dll 以检索本地时区。
  2. API 调用被 XenApp 拦截(请参阅是否可以为 Citrix XenApp 托管的应用程序获取用户时区?),因为 XenApp 可以配置为使用客户端的本地时区(请参阅http://mdaslam.wordpress.com/2010 /01/05/xenapp-time-zone-setting/)。
  3. 生成的TIME_ZONE_INFORMATION结构包含一个德语标准名称(我在英语 XenApp 服务器上使用 p/invoke 进行了检查)。
  4. 由于TIME_ZONE_INFORMATION结构(参见http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx)不包含语言中性时区标识符 .NET 无法匹配将德国时区标识符返回到其本地时区“数据库”(带有英文名称),并使用(本地化)标准名称作为时区的后备标识符。因此,TimeZoneInfo.Local.Id包含“本地”时区的德语名称。
  5. 然后TimeZoneInfo.FindSystemTimeZoneById这个备用标识符失败,因为系统确实不知道它(因为它是来自具有不同语言的系统的本地化标准名称)。

那么除了告诉客户在 XenApp 中禁用客户端时区的使用之外,我还能如何解决这个问题呢?

4

1 回答 1

1

这只是一个猜测,但很可能当 XenApp 映射客户端时区时,它正在使用GetTimeZoneInformation来自 Win32 API 的函数。这将返回一个TIME_ZONE_INFORMATION结构,其中不包括时区的 id。它只返回有关时区的信息,例如偏差和当前 DST 信息,以及本地化名称。

它可能应该改为 using GetDynamicTimeZoneInformation,它返回一个DYNAMIC_TIME_ZONE_INFORMATION结构。其中的元素之一是TimeZoneKeyName,它将映射回 .NETTimeZoneInfo.Id而不进行本地化。

现在我对 XenApp 知之甚少,但 Citrix 完全有可能已经意识到这个问题,并且要么已在最新版本中修复它,要么正在努力解决它。如果可能,您应该更新到最新版本,如果仍然损坏,请查看它是否列在他们的错误跟踪器中。如果没有,请报告并参考这篇文章。

于 2013-12-16T00:19:18.253 回答