2

My requirement is to read a particular registry key related to Adobe acrobat reader and take a decision based on the value of that key.

Though this seems straightforward like I need to query the key using Registry class (for .NET) and then take a decision based on the value.

However, the issue i face now is that, the registry key location keeps changing in almost every new version of Adobe Acrobat Reader.

All I can think of now is to have a switch case to handle for all the different Adobe versions in my code.

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

But some im not satisfied with this approach. Every time Adobe releases a new version i have to make sure i have to handle it differently. Any suggestions for a better approach.

Thanks

this-Me
  • 2,139
  • 6
  • 43
  • 70

3 Answers3

2

you best hope is to open the registry key containing the version numbers, then enumerate each sub key, possibly validating it looks like a version number, then look in each of those subkeys for the thing that you want. You might want to only use the highest number version that you find.

Obviously this will only work if what you want is always contained in the same registry entry relative to the version key, or always in the same named entry (and you would then have to enumerate every element under the sub key looking for the thing you want).

if the thing you want changes name and location in every release then you will have a problem, unless you can somehow recognize it from the data, in which case enumerate every element and look at the4 data and try to decide if it is what you want, but this approach is likely to be fraught with danger or false positives.

Sam Holder
  • 32,535
  • 13
  • 101
  • 181
0

Well, I have the exact same problem and since I know Adobe is not so brilliant in their decisions and makings, I think I will try this approach:

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

My registry has nothing related to Acrobat at :

HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\

..so it seems Adobe is moving their registry keys all over the registry with time passing... I just hope they will avoid moving Acrobat itself outside the Program Files folder in the future... (you never know with these people...)

NoOne
  • 3,851
  • 1
  • 40
  • 47
0

I think you can apply following logic: adobe file associations are kept in registry - you can read them under HKEY_CLASSES_ROOT \ .pdf \ OpenWithList

Those subkeys are app names (if any):

  • Acrobat.exe
  • AcroRD32.exe
  • etc.

Use them to combine and read keys (either Open or Read should be present)

  • HKEY_CLASSES_ROOT\Applications\XXXX\shell\Open\command
  • HKEY_CLASSES_ROOT\Applications\XXXX\shell\Read\command

If present, they would be similar to "C:\Program Files (x86)\Adobe\Acrobat 7.0\Acrobat\Acrobat.exe" "%1" from where you can strip %1 and get adobe app path.

Here is C# code:


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

When run GetAdobeApps, it returns collection similar to Count = 2 [0]: "C:\\Program Files (x86)\\Adobe\\Acrobat 7.0\\Acrobat\\Acrobat.exe" [1]: "C:\\Program Files (x86)\\Adobe\\Reader 9.0\\Reader\\AcroRd32.exe"
Sasha Bond
  • 984
  • 10
  • 13