Is an Application Associated With a Given Extension?

10,944

Solution 1

I would recommend following the advice in David's answer BUT since you need to detect an association:

To check whether a file has an association you can use the native function FindExecutable which is basically what Windows Explorer uses internally... it gives a nice error code (SE_ERR_NOASSOC) if there is no association. Upon success it gives a path to the respective executable.

Thee DllImport for it is

[DllImport("shell32.dll")]
static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);

Another option would be to walk the registry for example (not recommended since complex due to several aspets like WoW64 etc.):

The real association is stored in the key that HKEY_CLASSES_ROOT\.pdf points to - in my case AcroExch.Document, so we checkoutHKEY_CLASSES_ROOT\AcroExch.Document. There you can see (and change) what command is going to be used to launch that type of file:

HKEY_CLASSES_ROOT\AcroExch.Document\shell\open\command

Solution 2

@Yahia gets the nod. I'm posting my quick solution for posterity so you can see what I went with. There are lots of possible improvements to this code, but this will give you the idea:

public static bool HasExecutable(string path)
{
    var executable = FindExecutable(path);
    return !string.IsNullOrEmpty(executable);
}

private static string FindExecutable(string path)
{
    var executable = new StringBuilder(1024);
    FindExecutable(path, string.Empty, executable);
    return executable.ToString();
}

[DllImport("shell32.dll", EntryPoint = "FindExecutable")]
private static extern long FindExecutable(string lpFile, string lpDirectory, StringBuilder lpResult);

Solution 3

In a situation like this the best approach is to try to open the document and detect failure. Trying to predict whether or not a file association is in place just leads to you reimplementing the shell execute APIs. It's very hard to get that exactly right and rather needless since they already exist!

Solution 4

All of that information lives in the registry.. you could navigate to HKEY_CLASSES_ROOT, find the extension and go from there to find the default handler. But depending on the type of file and the associated handler(s) you'll need to wade into CLSIDs and whatnot... you're probably better off catching an exception instead.

Solution 5

This information is in the registry. For example:

# Mount the HKCR drive in powershell
ps c:\> new-psdrive hkcr registry hkey_classes_root
ps c:\> cd hkcr:\.cs

# get default key for .cs
PS hkcr:\.cs> gp . ""
(default)    : VisualStudio.cs.10.0
...

# dereference the "open" verb
PS hkcr:\.cs> dir ..\VisualStudio.cs.10.0\shell\open

    Hive: hkey_classes_root\VisualStudio.cs.10.0\shell\open

Name                           Property
----                           --------
Command                        (default) : "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe" /dde
ddeexec                        (default) : Open("%1")
Share:
10,944
bopapa_1979
Author by

bopapa_1979

I've been writing software for a living since my sophomore year in High School. I like to think I'm good at it, mostly. I have also doubled as a systems administrator, entrepeneur, business developer, and sometimes as a CTO of small companies. While I'm always interested in the latest and slickest approach to crafting software, I try to stay pragmatic and tend to think about technology in terms of revenues. My technology strengths are in Database Design and Programming (not so much optimization) and middleware. I'm very good at turning business rules into decision trees, and like to apply rules from the bottom up. I'm into SQL Server (and other flavors of SQL), .Net, C#, and building Web Applications. I'm slowly jumping on the web 2.0 bandwagon, and JavaScript, which was the red-headed stepchild of languages when I cut my web design teeth, is my next target to become an expert at.

Updated on June 03, 2022

Comments

  • bopapa_1979
    bopapa_1979 almost 2 years

    It is sometimes desirable to have your application open the default application for a file. For example, to open a PDF file you might use:

    System.Diagnostics.Process.Start("Filename.pdf");
    


    To open an image, you'd just use the same code with a different filename:

    System.Diagnostics.Process.Start("Filename.gif");
    


    Some extensions (.gif for example) just about always have a default handler, even in a base Windows installation. However, some extensions (.pdf for example) often don't have an application installed to handle them.

    In these cases, it'd be desirable to determine if an application is associated with the extension of the file you wish to open before you make the call to Process.Start(fileName).

    I'm wondering how you might best implement something like this:

    static bool ApplicationAssociated(string extension)
    {
        var extensionHasAssociatedApplication = false;
    
        var condition = // Determine if there is an application installed that is associated with the provided file extension.;
        if (condition)
        {
            extensionHasAssociatedApplication = true;
        }
    
        return extensionHasAssociatedApplication;
    }