Question

So I have this installer script that I wrote that automatically installs several different products on the target machine. At one point I'm checking to see if the machine (Windows 7) has Microsoft Security Essentials installed - if it doesn't then I install the program. This code below is written in C#, but the problem may be applicable to other languages as well.

Some facts to assist those with answering:

  • MSE is 64-bit on 64-bit machines and 32-bit on 32-bit machines (there are two different installers) Hence, the the path in the registry is always: SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall.
  • The process that is automating the install is run as administrator. I'm able to see the keys of other programs in the same directory.

My view in the Registry Editor:

enter image description here

My Method:

private static bool DoesMseExist()
{
    string location = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
    using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(location))
    {
         foreach (string subKey in rk.GetSubKeyNames())
         {
              using (RegistryKey productKey = rk.OpenSubKey(subKey))
              {
                  if (productKey != null)
                  {                     
                      if (Convert.ToString(productKey.GetValue("DisplayName"))
                                       .Contains("Microsoft Security Client"))
                      {
                         return true;
                      }
                  }
              }
         }
     }
     return false;
}

This never finds the key. Any assistance in discovering why would be much appreciated.

For the time being I am using the following as a substitute.

string MseLocation = @"C:\Program Files\Microsoft Security Client\msseces.exe";
return (File.Exists(MseLocation)); 
Was it helpful?

Solution

I'm currently using .NET 4.0 which provides a very clean solution for accessing the 64 bit registry from a 32 bit process. Otherwise, if you're using an earlier version of the Framework then you need to use P/Invoke and call the function RegOpenKeyEx with the KEY_WOW64_64KEY flag from the WINAPI as described here.

But onto the solution that I used.

private static bool DoesMseExist()
{
       using (RegistryKey localMachineX64View = 
                    RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, 
                    RegistryView.Registry64))
       {
           using (RegistryKey rk = localMachineX64View.OpenSubKey(location))
           {
               foreach (string subKey in rk.GetSubKeyNames())
               {
                   using (RegistryKey productKey = rk.OpenSubKey(subKey))
                   {
                       if (productKey != null)
                       {
                           if (Convert.ToString(productKey.GetValue("DisplayName"))
                              .Contains("Microsoft Security Client"))
                           {
                               return true;
                           }
                       }
                   }
               }
           }
      }
      return false;
}

I was writing a P/Invoke solution to this problem, but then I came across this. All you need to do is use RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) and you will overcome the registry redirection. It's a very easy to understand and readable approach compared to the P/Invoke solution, in my opinion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top