Microsoft.Win32.Registry's GetValue Doesn't Use Default Value - c#

I have a legacy (I didn't build it) application running on an x64 environment (Win7). I have a sneaking suspicion it was run on a 32-bit environment before.
Anyway, I see calls to Registry.GetValue(key, value, default).
It seems like the default value is ignored.
Check out this crazy code:
// Up above the sky, so high
using Microsoft.Win32;
// ...
string location = "HKEY_LOCAL_MACHINE\SOFTWARE\..."; // ...
// ...
string registryValue = (string)Registry.GetValue(location, "Uri", "http://localhost/");
if (string.isNullOrEmpty(registryValue) {
throw new Exception("What the ... ?!");
}
In a comparable example, the exception is seriously being thrown. (Actually, a null-reference exception appears despite the default value).
And I checked that I have the registry keys all the way up to the last level; they're all in my registry.
This works for someone, but not for me.
Is this a bug? What's going on here?

Most likely you are being caught out by registry redirection. You have a 32 bit process running on a 64 bit system. So HKLM\Software is redirected to HKLM\Software\Wow6432Node.
When the key does not exist, the Registry.GetValue returns null rather than the default value and so the exception is thrown.
If the name is not found in the specified key, returns a default value that you provide, or null if the specified key does not exist.

The default value is only returned if the specified key (that is the first parameter, i.e. location in your example) is found but a value with the specified name (the second parameter, "Uri" in your example) does not exist within that key.
If the key itself does not exist a null reference is returned.
This is fairly well documented on MSDN.
Probably the key you are looking for does not exist, probably because you are running on a 64-bit environment now which means that in case your application is a 32-bit process the HKLM\Software key gets mapped to HKLM\Software\Wow6432Node.

I know this is ancient, but in case anybody else stumbles upon this issue, I found an approach that works well for me. I'm using OpenSubKey, instead of GetValue.
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"Software\MyProduct");
string data = key.GetValue("MyValue") as string;
The registry's terminology caused me some confusion. It is not simply a key -> value store, it is more like key -> value -> data.

I've no idea why but i solved using
My.Computer.Registry.CurrentUser.GetValue("Software\Mykey","Default Value")
instead of
My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software","Mykey","Default Value")
If the key doesn't exist the first example returns "Default Value", the second a null object!

Related

Setting CheckBox value to checked

Some context, I'm still rather new at c# but I've been updating c# code that someone else wrote that is incomplete. I've come across this code that seems to be giving me an error.
gblnEnableSSL = Convert.ToBoolean(Convert.ToInt32(Utils.GetSetting("Program", "Configuration", "SSL", "0")));
Utils.GetSetting("Program", "Configuration", "SSL", "0") returns a string "false" currently.
I've found that removing Convert.ToInt32() solves my problem. But, I was unconvinced that someone simply added Convert.ToInt32() that broke the code. I checked in the repo and was surprised to find that the previous code of the same line use to be:
gblnEnableSSL = Utils.GetSetting("Program", "Configuration", "SSL", "0").ToUpper() == "TRUE";
Which seemed to work as well. The checkbox checked value is set by using chkEnableSSL.Value = gblnEnableSSL;
My question is whether or not there is a difference between setting the value using a bool value or a string value. Also, is a difference between chkEnableSSL.value vs chkEnableSSL.Checked?
Edit: I'm not getting a compiler or run-time error with the previous code. It does not perform the code afterwards. For example, i have txtDataSource.Text = strDataSource; immediately after and it does not set the text unless i comment out gblnEnableSSL = ... or remove the Convert.ToInt32().
Edit:Convert.ToInt32() throws an exception but it did not break in VS because i didn't have "Common Language Runtime Exceptions" checked off.
It looks like GetSetting is returning a string. The first code example you gave is converting this string to an integer and then converting it to a boolean. The only way this would work is if the string values stored for that key are either 0 or 1. On your second code block it looks as if the values being used were not string values of 0 or 1 but actual string values of true or false. If the values stored in your config file are still in the format of true or false then this would be why your first line is breaking. You can't convert false or true strings to an int. It does look like someone just added something to break the code.
Also you don't mention what technology you are using. You could be using winforms, wpf, webforms, or MVC. I'm going to assume this is a web technology you are using because checbox.value is something I usually see in javascript. General consensus in setting checkbox values in javascript is by using the .prop() property which takes in a string as the property you want to change and a value as the second parameter. E.G.
$( "input" ).prop( "checked", true );
http://api.jquery.com/prop/
Moral of the story is remove the conversion to the int32 and use .prop() to set that checkbox :)

Creating Calculator App in Windows Store

I am creating a Calculator in Windows Store Application. I have successfully created the app in the store.
Now there is a problem in my app, after getting the result from performing any operation whenever I press on any numeric value, that value got append in the existing value.
In the following snapshot: I have added two numbers (1,1):
Now I am entering another value to perform some other option, but the new value got append in the existing value. I am entering 1 here:
What is the code for removing the existing value, if any numeric values pressed?
you could declare a bool value which is false and when you have your calculation done you switch it to true. Then you write a method that checks if the calculation is done or not and if it's done you simply clear the (i guess you use a textblock / box?) output. That would be my way in this situation - maybe there is a better solution for you. I hope it helps you to get a clearer way in mind.
As the author of the Windows Calculator that shipped from Windows 3.0 through Windows Vista, I agree with user3645029's response. You need to work out the input model for the app, so you understand clearly when you begin entering a new number and when you append to the one showing. I suspect that your app logic isn't making this distinction.
Let me be more specific:
If the key pressed is a number and the last key pressed was a number, then you add that new digit, which effectively means multiplying the current value by 10 and then adding the new key.
If the key pressed is a number and the last key pressed was an operator, =, or similar keys, then you're starting a new number input and your current value should be reset to 0 first.
In short, writing a calculator app requires an internal state machines that understands how to proceed from one input to the next. From what you describe, it sounds like you're missing the logic for the = key. Generally speaking, hand-held calculators with an = sign effectively clear the current value if you start entering a new number after =. Only if you press an operator does that value persist, and in that case you're also starting a new current value and keeping the "2" in your case as the first operand.

Registry getValue with C#

I would like to read value in the registry using C#, if the values are not in the registry I create it. I have a reading problem:
RegistryKey regKey1 = Registry.CurrentUser;
regKey1 = regKey1.CreateSubKey(#"SOFTWARE\PNMDISPATCHER");
if (regKey1 != null)
{
textBoxTaux1.Text = regKey1.GetValue("Taux1").ToString();
}
I have the NullReferenceException when execute the GetValue function.
My values are in the registry, so why i get this error?
Looks like the RegistryKey.GetValue is returning null and cannot do .ToString()
Taken from MSDN for RegistryKey.GetValue:
Retrieves the value associated with the specified name. Returns null
if the name/value pair does not exist in the registry.
Well, apparently you didn't get the path right..
GetValue returns a Null when the key isn't found. Also check http://msdn.microsoft.com/en-us/library/fdf576x1
Can you debug through it and double check that the path you want to see, is indeed in the regKey1 variable at the textbox line?
Perhaps the NullReferenceException is for textBoxTaux1? Please post the call stack for the exception which should make this clear. You can use Exception.ToString() to get this.

Getting a value (on the right pane) from the registry

I'm trying to get a value from the registry in Windows, which sits under several branches:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\...
Given the following code:
RegistryKey openSubKey = settings.OpenSubKey(
#"\\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\DefaultSpoolDirectory");
openSubKey.SetValue("printername", "");
Where settings is set to LocalMachine in Microsoft.Win32.Registry.
However, I'd get null after the first line of code. What gives?
Two mistakes, \HKEY_LOCAL_MACHINE doesn't belong there, you should use Registry.LocalMachine instead. And DefaultSpoolDirectory doesn't belong there, it is a value, not a key.
The SetValue() arguments do not look happy either. If you want to add a printer (don't) then you'll need to add a key, not a value.
try removing "\hkey_local_machine"
Richard's answer seems correct, but just to inform you a little further, you can access the LocalMachine scope of the registry through the Registry.LocalMachine property - check this MSDN link for details. For an example, try this:
var openSubKey = Registry.LocalMachine.OpenSubKey(
#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers");

C# parse string "0" to integer

I have a new laptop at work and code that worked earlier in the week does not work today.
The code that worked before is, simplified:
while (dr.Read())
{
int i = int.Parse(dr.GetString(1))
}
Now it fails when the database value is 0. Sometimes, but not reliably, this will work instead:
while (dr.Read())
{
int i = Convert.ToInt32(dr["FieldName"]))
}
Am I missing something stupid?
Oddly enough, ReSharper is also having tons of weird errors with the same error message that I am getting with the above code: "input string was not in the correct format." (Starts before I even load a project.)
Any ideas? Anyone having any SP issues? I did try to make sure all my SPs were up-to-date when I got the machine.
EDIT: I understand how to use Try.Parse and error-handling. The code here is simplified. I am reading test cases from a database table. This column has only 0, 1, and 2 values. I have confirmed that. I broke this down putting the database field into a string variable s and then trying int.Parse(s). The code worked earlier this week and the database has not changed. The only thing that has changed is my environment.
To completely simplify the problem, this line of code throws an exception ("input string was not in the correct format"):
int.Parse("0");
EDIT: Thanks to everyone for helping me resolve this issue! The solution was forcing a reset of my language settings.
A possible explanation:
Basically, the problem was the
sPositiveSign value under
HKEY_CURRENT_USER\Control
Panel\International being set to 0,
which means the positive sign is '0'.
Thus, while parsing the "positive sign
0" is being cut off and then the rest
of the string ("") is parsed as a
number, which doesn't work of course.
This also explains why int.Parse("00")
wasn't a problem. Although you can't
set the positive sign to '0' through
the Control Panel, it's still possible
to do it through the registry, causing
problems. No idea how the computer of
the user in the post ended up with
this wrong setting...
Better yet, what is the output of this on your machine:
Console.WriteLine(System.Globalization.NumberFormatInfo.GetInstance(null).PositiveSign);
I'm willing to bet yours prints out a 0... when mine prints out a + sign.
I suggest checking your Control Panel > Regional and Language Options settings... if they appear normal, try changing them to something else than back to whatever language you're using (I'm assuming English).
I think it's generally not considered a good idea to call Convert.ToInt32 for the value reading out of database, what about the value is null, what about the value cannot be parsed. Do you have any exception handling code here.
Make sure the value is not null.
Check the value can be parsed before call Int32.Parse. Consider Int32.TryParse.
consider use a nullable type like int? in this case.
HTH.
Edit:
#Mike's response made me think that is extremely odd behavior and a simple google search yielded this result: int.Parse weird behavior
An empty string would also cause this issue.
You could check for dbnull before parsing, also it is good to validate parsed data.
You could use a default value and TryParse..
int i = -1;
if(!int.TryParse(dr["MyColumn"] as string, out i))
//Uh Oh!
Edit:
I posted this as a comment in #Chris' answer, but if the sql datatype is int then why not just use the GetInt32 method on the DataReater instead of retrieving it as a string and manual parsing it out?
Are you sure it's "0" and not "null"? What exception do you get?
EDIT:
Just out of curiosity, if it is really faulting on int.Parse("0"), can you try int.Parse("0", CultureInfo.InvariantCulture);?
Otherwise, post your query. Any joins?
you should check dr["FieldName"] != DBNull.Value and you should use TryParse if it passes the DBNull test...
if ( dr["FieldName"] != DBNull.Value )
{
int val = 0;
if ( int.TryParse( dr["FieldName"], out val ) )
{
i = val;
}
else
{
i = 0; // or some default value
}
}
I have seen this issue crop up with .NET Double class, parsing from string "0" as well.
Here's the really wacky part: you can get past the issue by using a different user account to run the program, and sometimes if you destroy and re-create the current user account on the machine, it will run fine.
I have yet to track this down, but you might get past it this way at least.
This is way out of left field, but check your localization settings. I had a number of "input string was not in a correct format" when I moved a web site to a Canadian server. The problem was in a DateTime.Parse method, and was fixed by setting the culture to "en-US".
Yes, your situation is different — but hey, you never know.
are you checking for null ?
if(!dr.IsNull("FieldName")){
int i = Convert.ToInt32(dr["FieldName"]))
}

Categories

Resources