我试图确定Windows系统的当前时区。以下代码片段(松散地)基于@MattJohnson在此主题中的答案:Getting local timezone identifier when OS display language is non-english
using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(
@"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"))
{
if (registryKey != null)
{
string windowsTimeZoneId = registryKey.GetValue("TimeZoneKeyName") as string;
if (string.IsNullOrEmpty(windowsTimeZoneId))
windowsTimeZoneId = registryKey.GetValue("StandardName") as string;
if (!string.IsNullOrEmpty(windowsTimeZoneId))
{
int i = windowsTimeZoneId.IndexOf('\0');
if (i != -1)
windowsTimeZoneId = windowsTimeZoneId.Remove(i);
return ConvertFromWindowsId(windowsTimeZoneId);
}
}
}
如果我在第一行" if(string.IsNullOrEmpty(windowsTimeZoneId))"上放置一个断点,那么这就是我在Visual Studio调试器中看到的:
这里发生了什么? RegistryKey.GetValue()返回一个盒装字符串,但为什么它没有检测到两个十六进制00字节并在那里终止字符串?
到目前为止,我已经在我的两台电脑上对此进行了测试。这是运行Windows 7 64位的。另一个运行Windows 7 32位的是相同的,除了它表示返回的字符串的长度是128个字符而不是127个。
使用regedit.exe查看注册表项时,它看起来很好,仅显示" Romance Standard Time"。
一些谷歌搜索出现了这个问题https://social.msdn.microsoft.com/Forums/sqlserver/en-US/eca7ad76-c910-46be-8fb9-876c7cde5c69/registry-read-time-zone-info-differ-when-code-build-on-40-framework-on-host-system-win-7-64-bit?forum=csharpgeneral否则我找不到任何东西。
该程序正在使用Visual Studio 2012构建,并以.Net 2.0为目标。
正如您所看到的,我已经添加了代码来解决此问题"腐败"结果考虑在内,但如果有人能向我解释这里发生了什么,甚至可能是如何避免整个问题,我仍然感激不尽。
编辑:
嗯,情节变浓了。那句话并不完全正确。上面显示的代码堆是在为.Net 2.0目标构建的库程序集中,但它是从一个针对.Net 4.0的程序调用的。现在我尝试从一个针对.Net 2.0的程序中调用它,并且没有问题,RegistryKey.GetValue()只返回"浪漫标准时间"。所以看起来它确实与.Net Framework 4.0有关,正如在MSDN上发布所暗示的那样。该程序正在使用Visual Studio 2012构建,并以.Net 2.0为目标。
编辑2 - 开始认为这是"正常"
对于SO而言,这有点偏离主题,但如果有人在Superuser.com上查看我的相关帖子,我会很感激,因为我没有在那里得到即时的满足感,并且我想解决这个问题,所以我知道我是否还应该恐慌。感谢。
https://superuser.com/questions/859031/possible-malware-modification-of-windows-registry-entry
答案 0 :(得分:2)
在注册表中设置字符串或多字符串值时,Windows不检查语义;它只是存储所提供的任何二进制内容,其长度由程序员指定。这意味着字符串可能过早地以空值终止,或者相反,根本不会以空值终止。 (顺便提一下,这确实有安全隐患:虽然我不认为过早的空终止可能会带来风险,但本地代码无法处理字符串未以空终止的情况。)
根据Hans(在他删除的答案中),如果字符串过早地以空值终止,则4.x之前的.NET版本将忽略额外数据,而4.x包括它。这就是为什么一旦开始使用4.x就会发现问题的原因。
至于为什么这个特殊值过早地被终止,这似乎是微软的粗心大意。如果删除额外数据,然后更改时区,则会再次显示额外数据。所以看起来Windows本身就是这样做的。数据看起来随意,所以我不相信这是故意的。事实上,这在技术上可能构成数据暴露漏洞,但可能没有实际影响。
我建议您搜索null并在必要时截断字符串。可能存在一种情况,例如,如果条目已经被第三方代码修改,或者MS最终发布更新并解决了问题,或者当然,如果您是'在.NET 2.x中重新运行。因此,您需要处理这两种情况。
(如果我有时间,下周回到工作岗位时,我会在虚拟机上安装一份干净的Windows副本,并确认问题是存在的,绝对没有第三方软件存在。如果有,我会考虑报告它 - 我怀疑MS会发布一个补丁,但它可能会在未来的Windows版本中修复。)