I'm writing code that sets a value in the Windows registry. when I set that value manually, it works as expected; when I want to set the value programmatically, however, it gives an error. The value I want to define is a DWORD value type that is "4294967295". When I define that in the script, though, it says that DWORD does not support this value. And, yet, I can assign that exact value via the program I am using to manually update the registry.
Here's my code:
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Lost in Days Studio\NO TIME", true);
key.SetValue("Current", 4294967295, RegistryValueKind.DWord);
key.Close();
As you likely know, a DWORD is stored as a 32 bit binary number. What may not be immediately obvious, though, is that it's unsigned—and, thus, a
UInt32(uint). Otherwise, you wouldn't be able to store a value of4294967295, since the maximum value for a signed integer (int) is 2,147,483,647.There's a catch, however! As @Jimi noted in the comments,
SetValue()will attempt to do aConvert.ToInt32(), which will cause an overflow with any value aboveInt32.MaxValue—thus the error you are receiving. One would expect it to useConvert.ToUInt32()but, as @Jimi also discovered, that is a known bug in the method, which Microsoft is unable to fix due to backward compatibility concerns.Instead, the
SetValue()method converts a signedInt32(int) into an unsigned 32 bit binary number, with values of0…2147483647remaining as is, but values of-2147483647…-1getting saved to the2147483648…4294967295range.That binary conversion is a bit convoluted if you're thinking about this as a signed integer. But, fortunately, you can use C#’s built-in
unchecked()keyword to permit the overflow and effectively treat youruintas a signedintwithin those ranges:This is really handy because it allows for you to continue to work with a standard
UInt32(uint) range of0…4294967295, exactly like you would via e.g. RegEdit, without having to think about how the binary conversion is being handled.