C#: Set File Type Association

ByMel

C#: Set File Type Association

While searching for some simple C# code to set the program and icon associated with a file type in Windows I ran across these beautiful functions that illustrate how to accomplish this by using the registry.

All credit goes to cristiscu (source).

Here’s the code:

using Microsoft.Win32;
using System.Runtime.InteropServices;

public class FileAssociation
{
    // Associate file extension with progID, description, icon and application
    public static void Associate(string extension, 
           string progID, string description, string icon, string application)
    {
        Registry.ClassesRoot.CreateSubKey(extension).SetValue("", progID);
        if (progID != null && progID.Length > 0)
            using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(progID))
            {
                if (description != null)
                    key.SetValue("", description);
                if (icon != null)
                    key.CreateSubKey("DefaultIcon").SetValue("", ToShortPathName(icon));
                if (application != null)
                    key.CreateSubKey(@"Shell\Open\Command").SetValue("", 
                                ToShortPathName(application) + " \"%1\"");
            }
    }

    // Return true if extension already associated in registry
    public static bool IsAssociated(string extension)
    {
        return (Registry.ClassesRoot.OpenSubKey(extension, false) != null);
    }

    [DllImport("Kernel32.dll")]
    private static extern uint GetShortPathName(string lpszLongPath, 
        [Out] StringBuilder lpszShortPath, uint cchBuffer);

    // Return short path format of a file name
    private static string ToShortPathName(string longName)
    {
        StringBuilder s = new StringBuilder(1000);
        uint iSize = (uint)s.Capacity;
        uint iRet = GetShortPathName(longName, s, iSize);
        return s.ToString();
    }
}

And here’s how you’d use it:

if (!FileAssociation.IsAssociated(".ext"))
   Associate(".ext", "ClassID.ProgID", "ext File", "YourIcon.ico", "YourApplication.exe");

A couple caveats to this code that I’ve noticed:

  1. The second parameter passed to Associate() can be any string you’d like to use to represent your program in the registry, just make sure you’re consistent with it.
  1. ToShortPathName() will return an empty string if the file path you pass it doesn’t exist, i.e. if you pass it a path to an icon file that doesn’t exist it won’t work.
  1. IsAssociated() will return true if the file extension is associated with any program, not just yours. If you want to be specific about it checking whether it’s associated with your program, then just check whether it’s default key is set to your programs ProgID.

About the author

Mel administrator

24 Comments so far

JustinPosted on9:39 am - Dec 10, 2017

I have a feeling Windows 10+ will never let you touch file associations again because they want to route all file association capability through the sandbox ecosystem of the Windows Store. This is disgusting.

GrsisFeePosted on8:37 am - May 12, 2015

Hello I have tried your method, but got nothing in windows 8.1.
In windows 8.1, your method could only add a Open Choice in the ContextMenu, it doesn’t change the default open program.
I am looking forward to receive your words. Thanks a lot.

    MelPosted on11:51 am - May 12, 2015

    I’m sorry but Windows 8 completely changed the way they handle default applications. As such the above solution won’t work entirely, as you’ve seen.

Dany TapiaPosted on5:48 pm - Sep 22, 2014

Hi, someone had problem with the associated icon?
it doesn’t show me the chosen one

BearPosted on9:09 pm - Oct 22, 2013

How to get the progID,I can only get the GUID !

    MelPosted on1:10 pm - Oct 23, 2013

    Hey Bear, “ClassID.ProgID” can be any string you want to uniquely identify your app, for example you could enter: “ThisIsMyAwesomeProgram” and that would work.

    You just need to make sure that you use that same string in each place where the ClassID.ProgID is requested.

JulienVPosted on12:04 am - Jul 31, 2012

OK I found the origin of my problem, I had to delete the key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\UserChoice which was overwriting the change made in registry.

JulienVPosted on11:52 pm - Jul 30, 2012

Hi, thanks for the code. I tried it but it doesn’t work for me. I’m trying to open “.log” files with my application by default, but they are still opened with Notepad after modifying the registry.
I tried to modify the ProgId from “txtfile” to my ProgId in the  HKEY_CLASSES_ROOT\.log or HKEY_CURRENT_USER\Software\Classes\.log keys.
 When I choose my application as default program by right-clicking on a log file it works but these registry keys are not modified I don’t understand… 

AidanPosted on8:46 pm - Jul 21, 2012

Thanks! This is the only thing I could find that worked after a lot of searches. One thing though, the icon wont show until you refresh the folder (if your folder is already open). This code refreshes the open windows:

[System.Runtime.InteropServices.DllImport(“Shell32.dll”)]
        private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);

davePosted on1:19 am - May 26, 2012

When I try to use this, I get this error:
 The name ‘Associate’ does not exist in the current context.

Any thoughts? Very new to C#. Thanks. 

    SerbPosted on8:37 am - Jul 6, 2012

    Hy Dave,

    Maybe You didn’t have copied all this code into your code. This code isn’t bulit in in the Framework so you must add this code to be able to use it.

    Best regard,
    Dule

HuyPosted on4:36 am - Dec 7, 2011

the icon does not show for the file association.

MazQuickPosted on10:59 am - Nov 29, 2011

Almost everything work, except icon being displayed.
I gave a path for the icon, but it doesn’t work anyway.
I tried using:
Application.StartupPath + @”\icon.exe”;
but it didn’t work, also I tried:
Application.ExecutablePath //(and added ,1 after it (in associate function)), but it also didn’t work.
 
Anyone know how to fix icon problem? :F

RobertPosted on7:21 pm - Apr 8, 2011

it is muh easy and fast to get the path if you use Application.StartUpPath(); function. that is the better way instead of using the DllImport attribute

china法宝Posted on10:53 pm - Nov 3, 2009

非常好。

Darth ReisenderPosted on8:36 pm - Oct 6, 2009

Promising, but… when I have my file type associated, how do I open it within my code, I mean, how does my app know that there is a file waiting to be opened?

    MelPosted on8:43 pm - Oct 6, 2009

    Hey Darth,

    If you’d like you’re application to handle files when it’s opened, such as if the user double-clicks on a file that you’ve associated with your program, you need to check for the path of the file in your program’s command-line arguments. Like so:

    string[] arguments = Environment.GetCommandLineArgs();
    if (arguments.Length > 1)
    {
        string filePath = arguments[1];
    }

    If you’d like to loop through all the files that might be sent to your program you can do it like this:

    string[] arguments = Environment.GetCommandLineArgs();
    for (int i = 1; i < arguments.Length; i++)
    {
        string filePath = arguments[i];
    }

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.