0

所以我有我编写的这个安装程序脚本,它可以在目标机器上自动安装几个不同的产品。在某一时刻,我正在检查机器(Windows 7)是否安装了Microsoft Security Essentials - 如果没有,那么我安装该程序。下面的代码是用 C# 编写的,但该问题也可能适用于其他语言。

一些有助于回答的事实:

  • MSE 在 64 位机器上是 64 位,在 32 位机器上是 32 位(有两个不同的安装程序)因此,注册表中的路径始终是:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
  • 自动安装的过程以管理员身份运行。我可以看到同一目录中其他程序的键。

我在注册表编辑器中的视图:

在此处输入图像描述

我的方法:

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;
}

这永远找不到钥匙。任何有助于发现原因的帮助将不胜感激。

目前我正在使用以下内容作为替代品。

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

1 回答 1

0

我目前正在使用 .NET 4.0,它为从 32 位进程访问 64 位注册表提供了一个非常干净的解决方案。否则,如果您使用的是较早版本的框架,则需要使用 P/Invoke 并使用此处所述RegOpenKeyExKEY_WOW64_64KEY标志调用函数。WINAPI

但是在我使用的解决方案上。

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;
}

我正在为这个问题编写一个 P/Invoke 解决方案,但后来我遇到了这个. 您需要做的就是使用RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64),您将克服注册表重定向。在我看来,与 P/Invoke 解决方案相比,这是一种非常容易理解和可读的方法。

于 2013-10-05T00:16:57.830 回答