How can I get the description of a file extension in .NET

You can use the SHGetFileInfo API to get that information. Here's a wrapper method:

    public static string GetFileTypeDescription(string fileNameOrExtension)
    {
        SHFILEINFO shfi;
        if (IntPtr.Zero != SHGetFileInfo(
                            fileNameOrExtension,
                            FILE_ATTRIBUTE_NORMAL,
                            out shfi,
                            (uint)Marshal.SizeOf(typeof(SHFILEINFO)),
                            SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME))
        {
            return shfi.szTypeName;
        }
        return null;
    }

    [DllImport("shell32")]
    private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags);

    [StructLayout(LayoutKind.Sequential)]
    private struct SHFILEINFO
    {
        public IntPtr hIcon;
        public int iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    }

    private const uint FILE_ATTRIBUTE_READONLY = 0x00000001;
    private const uint FILE_ATTRIBUTE_HIDDEN = 0x00000002;
    private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
    private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
    private const uint FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
    private const uint FILE_ATTRIBUTE_DEVICE = 0x00000040;
    private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
    private const uint FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
    private const uint FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
    private const uint FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
    private const uint FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
    private const uint FILE_ATTRIBUTE_OFFLINE = 0x00001000;
    private const uint FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
    private const uint FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
    private const uint FILE_ATTRIBUTE_VIRTUAL = 0x00010000;

    private const uint SHGFI_ICON = 0x000000100;     // get icon
    private const uint SHGFI_DISPLAYNAME = 0x000000200;     // get display name
    private const uint SHGFI_TYPENAME = 0x000000400;     // get type name
    private const uint SHGFI_ATTRIBUTES = 0x000000800;     // get attributes
    private const uint SHGFI_ICONLOCATION = 0x000001000;     // get icon location
    private const uint SHGFI_EXETYPE = 0x000002000;     // return exe type
    private const uint SHGFI_SYSICONINDEX = 0x000004000;     // get system icon index
    private const uint SHGFI_LINKOVERLAY = 0x000008000;     // put a link overlay on icon
    private const uint SHGFI_SELECTED = 0x000010000;     // show icon in selected state
    private const uint SHGFI_ATTR_SPECIFIED = 0x000020000;     // get only specified attributes
    private const uint SHGFI_LARGEICON = 0x000000000;     // get large icon
    private const uint SHGFI_SMALLICON = 0x000000001;     // get small icon
    private const uint SHGFI_OPENICON = 0x000000002;     // get open icon
    private const uint SHGFI_SHELLICONSIZE = 0x000000004;     // get shell size icon
    private const uint SHGFI_PIDL = 0x000000008;     // pszPath is a pidl
    private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;     // use passed dwFileAttribute

(most of the constants aren't actually used in that code, but I put them anyway in case you want to adapt the code to your specific needs)


When you use SHGetFileInfo, normally the file must exist on disk. If you only have the name of the file, or even just the extension, you will need to pass in the SHGFI_USEFILEATTRIBUTES flag during the call.

Alternatively, you can get the information directly from the registry:

public static string GetFileTypeDisplayName(string extension) =>
    Registry.ClassesRoot.OpenSubKey(extension)?.GetValue(null) is string keyName ?
        Registry.ClassesRoot.OpenSubKey(keyName)?.GetValue(null) as string :
        null;

This method will simply return null if there is no suitable entry in the registry for the given file extension.


You can search the registry like this:

  • Search default value of the extension in HKEY_CLASSES_ROOT. For example The default value of HKEY_CLASSES_ROOT\.txt is txtfile.
  • Then search default value of the previous result: For example The default value of HKEY_CLASSES_ROOT\txtfile is Text Document.

After two searches the answer is Text Document.

You can test any other extension by RegEdit.

Visit this link: http://www.codeproject.com/KB/cs/GetFileTypeAndIcon.aspx?display=Print

This is implementation of these two searches:

public static class Helper
{
    public static string GetFileDescription(string fileName)
    {
        if (fileName == null)
        {
            throw new ArgumentNullException("fileName");
        }

        RegistryKey registryKey1 = null;
        RegistryKey registryKey2 = null;
        try
        {
            FileInfo fileInfo = new FileInfo(fileName);

            if (string.IsNullOrEmpty(fileInfo.Extension))
            {
                return string.Empty;
            }

            string extension = fileInfo.Extension.ToLowerInvariant();

            registryKey1 = Registry.ClassesRoot.OpenSubKey(extension);
            if (registryKey1 == null)
            {
                return string.Empty;
            }

            object extensionDefaultObject = registryKey1.GetValue(null);
            if (!(extensionDefaultObject is string))
            {
                return string.Empty;
            }

            string extensionDefaultValue = (string)extensionDefaultObject;

            registryKey2 = Registry.ClassesRoot.OpenSubKey(extensionDefaultValue);
            if (registryKey2 == null)
            {
                return string.Empty;
            }

            object fileDescriptionObject = registryKey2.GetValue(null);
            if (!(fileDescriptionObject is string))
            {
                return string.Empty;
            }

            string fileDescription = (string)fileDescriptionObject;
            return fileDescription;
        }
        catch (Exception)
        {
            return null;
        }
        finally
        {
            if (registryKey2 != null)
            {
                registryKey2.Close();
            }

            if (registryKey1 != null)
            {
                registryKey1.Close();
            }
        }
    }
}

Tags:

Windows

.Net