C#操作注册表REG_DWORD类型键异常(RegistryValueKind.DWord异常)解决方案
在用C#操作注册表时,如果注册表键的类型是REG_DWORD,有可能遇到溢出BUG。网上这方面的资料很少,在这共享一下。
C#可以用RegistryKey类的SetValue方法来设置键值,例如:
看起来一切正常,但是这个RegistryValueKind.DWord是有问题的。
注册表中的REG_DWORD是无符号32位数值,而C#中的RegistryValueKind.DWord是有符号32位数值。这就意味着RegistryValueKind.DWord的表示范围比REG_DWORD小,因此导致直接传入一些大数时会抛出异常提示类型不正确。
那么如何解决这个BUG呢?
读者可能试图这样做:
openKey.SetValue("NoViewOnDrive",Convert.ToInt32("ffffffff",16), RegistryValueKind.DWord);
目的是强制把参数转换成32位有符号数,这样是不行的,同样提示异常,因为ffffffff已经超出了有符号32位数的表示范围,无法转换。
或者这样做:
openKey.SetValue("NoViewOnDrive",Convert.ToUInt32 ("ffffffff",16), RegistryValueKind.DWord);
目的是把参数强制转换成无符号32位表示,这样同样不行,SetValue方法内部会自动把参数转换成有符号32位表示,因此,我们的转换是徒劳的,还会被转换回去,而转换回去后,又会提示超出范围。
其实,解决这个问题的方法很简单,只要把转换过程放在unchecked语句里就行了,unchecked语句块内的转换,不做溢出检查,溢出了直接用补码表示。例如:
Int32 tempInt = 0; //预先定义一个有符号32位数 //unchecked语句块内的转换,不做溢出检查 unchecked { tempInt = Convert.ToInt32("ffffffff", 16); //强制转换成有符号32位数 } //此时的tempInt已经是有符号32位数,可以直接写入注册表 openKey.SetValue("NoViewOnDrive", tempInt, RegistryValueKind.DWord);
这样转折一下,就可以成功写入注册表了。