Click here to Skip to main content
15,897,187 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have the following code:

The values are displayed as follows in the debugger:
FF86_version "31.0.1"
FF86_name "Firefox"
displayFF86version "null"
displayFF86name "null"

C#
public static bool checkFF86version(string FF86_name, string FF86_version)
{
    RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
    .OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
    //.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
    string displayFF86version;
    string displayFF86name;

    if (key != null)
    {
        foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
        {
            displayFF86name = subkey.GetValue("DisplayName") as string;
            if (displayFF86name != null && displayFF86name.Contains(FF86_name))
            {
                displayFF86version = subkey.GetValue("DisplayVersion") as string;

            if (displayFF86version.Equals(FF86_version))
                {
                    var version = displayFF86version; //Comes from the Registry
                    var parsedversion = Version.Parse(version);

                    var minimumversion = new Version(FF86_version); //Static Version Check

                    if (parsedversion >= minimumversion)
                        return true;
                }
            }
            return false;
        }
    }
    return false;


I am trying to see if "Firefox" is installed. If it is detected compare the DisplayVersion to see if it is > or < the version identified as displayed below:

C#
if (checkFF86version("Firefox", "31.0.1"))
   listView1.Items.Add(new ListViewItem { ImageIndex = 0, Text = "Firefox is Installed and is the latest version" });
else
    listView1.Items.Add(new ListViewItem { ImageIndex = 0, Text = "Firefox needs updated" });



I am not receiving any NullReferenceException's and the code is running perfectly fine, but it is producing "NULL" data from the key strings like it is not looping propperly as stated above. Any help anyone could provide will be greatly appreciated.

Thanks!
Posted
Comments
Sergey Alexandrovich Kryukov 26-Oct-14 14:24pm    
First, please explain: why would you expect NullReferenceException, in what line(s)?
Having something equal to null does not mean exception.
After all, if you suspect that the code under the debugger is executed in different way (in rare cases, it happens, say, due to race conditions), check for null and output the result of this check on screen or somewhere.
—SA
mikem001 26-Oct-14 14:37pm    
I am not expecting a null return... I am expecting

displayFF86version = "The value of the DisplayVersion string"
displayFF86name = "The value of the DisplayName string"

The keys are in the registry and if I look test this method using this:

<pre lang="C#">public static bool checkFF86Installed(string FF86_Name)
{
RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
string displayFF86Name;

if (key != null)
{
foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
{
displayFF86Name = subkey.GetValue("DisplayName") as string;
if (displayFF86Name != null && displayFF86Name.Contains(FF86_Name))
{
return true;
}
}</pre>

I can see the name returned. This proves the same for the version if edited as such:

<pre lang="c#">public static bool checkFF86version(string FF86_version)
{
RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
string displayFF86Version;

if (key != null)
{
foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
{
displayFF86Version = subkey.GetValue("DisplayVersion") as string;
if (displayFF86Version != null && displayFF86Version.Equals(FF86_version))
{
return true;
}
}
// key.Close();
}
return false;
}</pre>

I am trying to combine this so it will take the key name found and look at that keyname for the string "DisplayVersion" and compare the DisplayVersion to the static version I have identified. This will tell me if the version found is newer or older than the checked static version.

Maybe I am doing this all wrong?
[no name] 26-Oct-14 15:16pm    
You should expect a null reference which is probable to happen with these variables:
string displayFF86version;
string displayFF86name;
as a result of how you've wrote your if statements
mikem001 26-Oct-14 15:36pm    
I think I now know why I am receiving null, I am not looping through the keys in "Uninstall" It seems to only be checking the first key and producing null as it should if it is not looping through all the keys in Uninstall. Can you tell why it is not looping. Is it because of the if statements that are in the loop?
[no name] 26-Oct-14 15:53pm    
The issue is your For statement, as you are specifically telling it to look into one subkey which is why the other sub keys don't get processed. And that's why I said you should expect a null reference on those variables above. Take a look at my solution, as I've outlined some other issues in your code too. Hope you find my answers, useful.

One thing; the registry is not always going to contain this information on every program, so you should have an Else statement to check the sub key in the registry: InstallLocation if the DisplayName is not null, then the program is installed, so look for an install path in the registry sub key InstallLocation, and get the file version from the actual file build using System.IO fileinfo properties if you know the file name.

(the only issue you have here is knowing what the file name of the executable is; because that's nearly never available in the Uninstall section of the registry sub keys.) I am sure the path is stored somewhere in the registry... for that you will have to research or maybe someone here will know.

Secondly, you are using a boolean here: if (displayFF86version.Equals(FF86_version)) because the equals represents a Boolean check to see if its a match to the variable you pass to .Equals() which will always return false if the value does not exist or is not a match. You should also check if displayFF86version is not null first prior to the statement above:
C#
if (!(displayFF86version == Null)) {
//Do action here
}
and if it is null, then either cypher through WMI for the Executable path for the file name in order to get the file version as suggested above. Something like this might work for WMI searching:
C#
{
	Management.ManagementObjectCollection ManobjectReturn = default(Management.ManagementObjectCollection);
	Management.ManagementObjectSearcher ManobjectSearch = default(Management.ManagementObjectSearcher);
	Management.ManagementObject Manobject = default(Management.ManagementObject);
	ManobjectSearch = new Management.ManagementObjectSearcher("Select * from Win32_Product");
	ManobjectReturn = ManobjectSearch.Get;
	foreach ( Manobject in ManobjectReturn) {
		string Address = Convert.ToString(Manobject("InstallLocation"));
		string NewExeName = Convert.ToString(Manobject("Name"));
		Interaction.MsgBox(string.Format("{0} Location {1} ", Manobject("Name"), Manobject("InstallLocation")));

		//Do your If Checks here for each program. 

	}
}


One other thing in your Conditional operator logic:
C#
if (parsedversion >= minimumversion)
                            return true;
                    }

The Parsed version is going to be the file version, and assuming minimumversion is meant to be the latest available version, your logic should be <= less than or equal to; because your parsed version will never be greater than the available version.

Apart from that, your code looks Ok.
 
Share this answer
 
Comments
BillWoodruff 26-Oct-14 18:24pm    
+5
[no name] 26-Oct-14 18:49pm    
Once again, thank you kindly.
Alter this into your code instead of the methods you are using. And use my variables or else you can = them to your own, if you are not bothered to change them. I have added some filtering here to stop Hotfixes and updates and alike from being added from the loop. These are optional and can be enabled by using the Boolean variable. You can see the results in your console when you run it in the debugger as seen in the attached image.

This code is tested and working. Please don't forget to rate, and mark as a solution. If you have any questions after you do so; I will be happy to help.
C#
public void GetNameAndVersion()
{
	Microsoft.Win32.RegistryKey iRegKey = null;
	Microsoft.Win32.RegistryKey iSubKey = null;
	string eValue = null;
    string eVersion = null;
	string regpath = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
	iRegKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(regpath);
	string[] subkeys = iRegKey.GetSubKeyNames();
	bool includes = false;
	foreach (string subk in subkeys) {
		iSubKey = iRegKey.OpenSubKey(subk);
		eValue = Convert.ToString (iSubKey.GetValue("DisplayName", ""));
        eVersion = Convert.ToString(iSubKey.GetValue("DisplayVersion", ""));
		if (!string.IsNullOrEmpty(eValue)) {
			includes = true;
			if (eValue.IndexOf("Hotfix") != -1)
				includes = false;
			if (eValue.IndexOf("Security Update") != -1)
				includes = false;
			if (eValue.IndexOf("Update for") != -1)
				includes = true;
			if (includes == true)
				Console.WriteLine ( eValue );
		}
        if (!string.IsNullOrEmpty(eVersion))
        {
            includes = true;
            if (eVersion.IndexOf("Hotfix") != -1)
                includes = false;
            if (eVersion.IndexOf("Security Update") != -1)
                includes = false;
            if (eVersion.IndexOf("Update for") != -1)
                includes = true;
            if (includes == true)
                Console.WriteLine(eVersion);
        }
	}
}

Result:

Fix
 
Share this answer
 
Comments
[no name] 26-Oct-14 18:15pm    
So can you see the difference in what you were doing wrong compared to my method? Let me know if you have any questions or need help making alterations.
mikem001 26-Oct-14 18:19pm    
Yes, I think I can see now. I have been studying your code and am only stumped in one place it seems. Now thanks to you I can loop all the keys looking at the DisplayVersion and DisplayName. It seems that your code is requesting (Equals) the data. I am trying to get it to:
Contains for the DisplayName and Equals for the DisplayVersion
mikem001 26-Oct-14 18:44pm    
I will continue to research this function as I simply need to learn more about it. I would like to thank you for taking the time out of your schedule to help me with the logic. I promise you it will not go to waste. I just feel like I need to read more Tech Net to fully understand what you have achieved.
[no name] 26-Oct-14 18:52pm    
Which function are you referring to Mike? As we kinda covered a lot on your question.

And I don't mind answering any questions you have regarding anything you may wish to look-up. I be happy to answer them for you.
mikem001 26-Oct-14 19:03pm    
I am looking at:

if (!string.IsNullOrEmpty(eValue))

I know I cannot use this as currently written, but it gives an idea as to what I would like to do...

if (!string.IsNullOrEmpty.Contains(eValue))
I have come up with the following solution, and was wondering if I could get it everyone to look at it and see if you agree with this solution. It does exactly as it says, but I know there are additional checks I can put in... Your thoughts!

C#
        public void GetNameAndVersion()
        {
            Microsoft.Win32.RegistryKey iRegKey = null;
            Microsoft.Win32.RegistryKey iSubKey = null;
            string eValue = null;
            string eVersion = null;
            string regpath = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
            iRegKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(regpath);
            string[] subkeys = iRegKey.GetSubKeyNames();
            bool includes = false;
            foreach (string subk in subkeys)
            {
                iSubKey = iRegKey.OpenSubKey(subk);
                 eValue = Convert.ToString(iSubKey.GetValue("DisplayName", ""));
                 eVersion = Convert.ToString(iSubKey.GetValue("DisplayVersion", ""));

                 if (eValue != null && eValue.Contains("Firefox"))
                 {
                    var version = eVersion;
                     var parsedversion = Version.Parse(version);
                     var minimumversion = new Version("35.0.1");

                     if (parsedversion >= minimumversion)
                         listView1.Items.Add(new ListViewItem { ImageIndex = 0, Text = "Firefox is the latest version or newer" });
                     else if (parsedversion < minimumversion)
                         listView1.Items.Add(new ListViewItem { ImageIndex = 0, Text = "Firefox needs reinstalled" });
                 
                 else
                     includes = false;
                 }
            }
        }
    }
}
 
Share this answer
 
Comments
[no name] 26-Oct-14 20:40pm    
Hi Mike, may I process your code tomorrow as It is getting late, and I would like to make some alterations if you don't mind. It looks good at a glance, but there are some thing's I may tweak if you don't mind?
mikem001 26-Oct-14 21:06pm    
Sure, I am glad you are taking the time to help me learn. I am very thankful for everything you have provided. I am looking forward to seeing what you have to add.
[no name] 26-Oct-14 21:29pm    
I am happy to teach you to learn by any experience I can offer you Mike; you know I don't forget my routes either; and I remember where I started, and it wasn't on this site sadly, or I would have learned faster.

I'll see what I can conjure up for you tomorrow, so have yourself a good night and we will speak tomorrow.

Kind Regards
[no name] 27-Oct-14 19:47pm    
I made a change or two regarding your alterations to my code.
if (eValue != null && eValue.Contains("Firefox"))
This check is a little pointless, because eValue is always going to be something since it's been iterated. And also checking that it contains a file name limits it to an individual file.

So see the change I made in the new solution Now you can pass variable parameters to the function which is not limiting you from checking other files also. You could iterate a bunch of file names and send them to the function repeatedly to check a number of applications from ' Run '.
C#
private void Main_Load(object sender, EventArgs e)
        {
            {


                Run();
            }
        }
        private void Run()
{
	//The call to this function will require you to know the new version number of the program to compare it in the called function. 
    if (GetNameAndVersion(Program: "Visual Studio Premium 2012", Version: "11.0.50727") == true)
        //Put if statement here to check eError is True, if it is, message box to the user, else execute the statement below to add to listbox.
    {
        listView1.Items.Add(new ListViewItem
        {
            ImageIndex = 0,
            Text = "This is the latest version."
        });

    }
    else
    {
        listView1.Items.Add(new ListViewItem
        {
            ImageIndex = 0,
            Text = "Update is available for download."
        });
    }
}
        string eValue = null;
        bool eError = false;
        string eVersion = null;
        public bool GetNameAndVersion(string Program, string Version)
        {
            Microsoft.Win32.RegistryKey iRegKey = null;
            Microsoft.Win32.RegistryKey iSubKey = null;

            string regpath = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
            iRegKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(regpath);
            string[] subkeys = iRegKey.GetSubKeyNames();
            bool includes = false;
            foreach (string subk in subkeys)
            {
                iSubKey = iRegKey.OpenSubKey(subk);
                eValue = Convert.ToString(iSubKey.GetValue("DisplayName", ""));
                eVersion = Convert.ToString(iSubKey.GetValue("DisplayVersion", ""));


                Console.WriteLine(eValue + " " + eVersion);
                if (eValue.Contains(Program) && eVersion != null)
                {
                    if (!eVersion.Equals (Version))
                    {

                        return false;
                    }
                    else if (eVersion.Equals (Version))
                    {
                         return true;
                    }
                }

            }
            //Catch block ends here
            eError = true; 
            return true;
        }


The only thing about this, is that you need to know what the latest version numbers are in order to get a positive result for an update. Also wrap the registry part in a try exception block to deal with restrictions which might arise.
 
Share this answer
 
v2
Comments
mikem001 27-Oct-14 20:07pm    
You know I was researching today this exact same thing. I noticed last night that the way I had it written out, I would have to repeat the code for each software I needed to check for. You have read my mind. This is truly the best solution for my project out of all of them. They all work great, but this is definitely the best for my current needs. My hats off to you and your skills.
mikem001 27-Oct-14 20:08pm    
By the way you have taught me a great deal here, and I will continue to implement as I move forward in designing. Thanks again!
[no name] 27-Oct-14 20:43pm    
No problem Mike, you're welcome, and I am glad I could be of help to you and your project.

Take care.
mikem001 27-Oct-14 21:18pm    
I did find a typo here, it seems that if I am correct the last return should be "return false;"
[no name] 27-Oct-14 21:27pm    
Not a typo at all, just something you need to handle should none of the above conditions be met, then that return statement should be True or else you will get the message: Text = "Update is available for download."
Which is lies, what I would do is declare a global bool somewhere in your main class and set it to true or false and when that section that you mentioned is reached: }
}
} return true;
you can handle that when you are returned to the calling thread by checking your new bool value, and if its true, then tell them that there was an issue trying to retrieve the information from the registry.

See edited solution in a minute.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900