C# Adobe acrobat reader注册表项位置不断更改

C# Adobe acrobat reader注册表项位置不断更改,c#,registry,acrobat,C#,Registry,Acrobat,我的要求是读取与Adobe acrobat reader相关的特定注册表项,并根据该项的值做出决定 private void AddShellCommandDefault(List<string> lst, RegistryKey shell, string reg KeyOpenRead) { var shellOpen = shell.OpenSubKey(regKeyOpenRead); if (shellOpen == null) return;

我的要求是读取与Adobe acrobat reader相关的特定注册表项,并根据该项的值做出决定

private void AddShellCommandDefault(List<string> lst, RegistryKey shell, string reg  KeyOpenRead)
{
    var shellOpen = shell.OpenSubKey(regKeyOpenRead);
    if (shellOpen == null) return;

    var shellOpenCommand = shellOpen.OpenSubKey("command");
    if (shellOpenCommand == null) return;

    var defaultVal = shellOpenCommand.GetValue(null);
    if (defaultVal == null) return;

    int kex = defaultVal.ToString().LastIndexOf(".exe", StringComparison.OrdinalIgnoreCase);
    if (kex < 0) return;

    lst.Add(defaultVal.ToString().Substring(0, kex).Replace("\"", "") + ".exe");
}

public List<string> GetAdobeApps()
{
    var addobeList = new List<string>();

    // HKEY_CLASSES_ROOT\.pdf\OpenWithList\Acrobat.exe
    // HKEY_CLASSES_ROOT\Applications\Acrobat.exe\shell\Open\command
    //  default "C:\Program Files (x86)\Adobe\Acrobat 7.0\Acrobat\Acrobat.exe" "%1"

    var adobe = Registry.ClassesRoot.OpenSubKey(".pdf");
    if (adobe == null) return addobeList;

    var openWith = adobe.OpenSubKey("OpenWithList");
    if (openWith == null) return addobeList;

    var apps = Registry.ClassesRoot.OpenSubKey("Applications");
    if (apps == null) return addobeList;

    foreach (string sLong in openWith.GetSubKeyNames())
    {
        string s = sLong.Split(@"\/".ToCharArray()).Last();
        var adobeApp = apps.OpenSubKey(s);
        if (adobeApp == null) continue;

        var shell = adobeApp.OpenSubKey("shell");
        if (shell == null) continue;

        AddShellCommandDefault(addobeList, shell, "Read");
        AddShellCommandDefault(addobeList, shell, "Open");
    }

    return addobeList;
}        
虽然这看起来很简单,但我需要使用注册表类(对于.NET)查询键 然后根据价值做出决定

然而,我现在面临的问题是,在几乎每个新版本的Adobe Acrobat Reader中,注册表项的位置都在不断变化

我现在所能想到的就是在我的代码中为所有不同的Adobe版本处理一个切换用例

RegistryKey adobe = Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Adobe");
            if (adobe != null)
            {
                RegistryKey acroRead = adobe.OpenSubKey("Acrobat Reader");
                if (acroRead != null)
                {
                    string[] acroReadVersions = acroRead.GetSubKeyNames();
                    Console.WriteLine("The following version(s) of Acrobat Reader are installed: ");
                    foreach (string versionNumber in acroReadVersions)
                    {
                        switch(versionNumber)
                        {
                           case 1.x = //do something;
                                      //break;    
                           case 2.x = //do something;
                                      //break;
                           case 6.x = //do something;
                                      //break;
                           case 9.x = //do something;
                                      //break;
                        }  
                    }
                }
            }
但有些人对这种方法并不满意。每次Adobe发布新版本时,我都必须确保以不同的方式处理它。任何关于更好方法的建议


谢谢

您最好打开包含版本号的注册表项,然后枚举每个子项,可能会验证它看起来像一个版本号,然后在每个子项中查找您想要的内容。您可能只想使用找到的最高版本

显然,只有当您想要的内容始终包含在与版本项相关的同一注册表项中,或者始终包含在同一命名项中(然后您必须枚举子项下的每个元素以查找您想要的内容)时,这才有效


如果您想要的东西在每个版本中都更改了名称和位置,那么您将遇到问题,除非您能够从数据中以某种方式识别它,在这种情况下,枚举每个元素并查看4个数据并尝试确定它是否是您想要的,但这种方法可能充满危险或误报,我也有同样的问题,因为我知道Adobe在决策和决策方面没有那么出色,我想我会尝试以下方法:

    public static string AcrobatReaderPath
    {
        get
        {
            var paths = new List<string>()
                    {
                        Registry.GetValue(@"HKEY_CLASSES_ROOT\Software\Adobe\Acrobat\Exe", "", @"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe") as string
                    };
            var files = Directory.GetFileSystemEntries(@"C:\Program Files (x86)\Adobe\", @"*Acr*R*d*32.exe", SearchOption.AllDirectories);
            paths.AddRange(files);
            foreach(var path in paths) if (File.Exists(path)) return path;
            return "";
        }
    }
公共静态字符串AcrobReaderPath
{
得到
{
变量路径=新列表()
{
Registry.GetValue(@“HKEY\U CLASSES\U ROOT\Software\Adobe\Acrobat\Exe”,“”,@“C:\Program Files(x86)\Adobe\Reader 10.0\Reader\AcroRd32.Exe”)作为字符串
};
var files=Directory.getfilesystem(@“C:\Program files(x86)\Adobe\”、@“*Acr*R*d*32.exe”、SearchOption.AllDirectories);
path.AddRange(文件);
foreach(路径中的var路径)if(File.Exists(path))返回路径;
返回“”;
}
}
我的注册表与Acrobat无关,地址为:

HKEY\U LOCAL\U MACHINE\SOFTWARE\Adobe\

…所以Adobe似乎随着时间的推移在整个注册表中移动他们的注册表项。。。
我只是希望他们以后不要把Acrobat本身移到ProgramFiles文件夹之外。。。(你永远不知道这些人…

我认为你可以应用以下逻辑: adobe文件关联保存在注册表中-您可以在 HKEY\U CLASSES\U ROOT\.pdf\OpenWithList

这些子键是应用程序名称(如果有):

  • Acrobat.exe
  • AcroRD32.exe
  • 等等
使用它们组合和读取键(应存在打开读取

  • HKEY\U CLASSES\U ROOT\Applications\XXXX\shell\Open\command
  • HKEY\U CLASSES\U ROOT\Applications\XXXX\shell\Read\command
如果存在,它们将类似于 C:\Program Files(x86)\Adobe\Acrobat 7.0\Acrobat\Acrobat.exe“%1” 您可以从中剥离%1并获取adobe应用程序路径

以下是C#代码: