9

HI,

Windows provides descriptions for file extension such as "Control Panel Item" for .cpl files and "PowerISO File" for .daa files. Is there any way I can obtain this data in .NET ? Im using C# but can read all the other .NET languages. Also is there a way to obtain the default icon of the extensions as well ? Any help would be appreciated.

Thanks in advance

Stewart Stoakes
  • 797
  • 1
  • 8
  • 13
  • Very similar to http://stackoverflow.com/questions/1910097/content-type-by-extension – David Sep 23 '10 at 15:47
  • 1
    @David Stratton, this is NOT the same question. The question you mention is about getting the content type (MIME type). This one is about getting the description for the file type. – Thomas Levesque Sep 23 '10 at 15:51
  • 1
    possible duplicate of [Get file type in .NET](http://stackoverflow.com/questions/1437382/get-file-type-in-net) – Hans Passant Sep 23 '10 at 16:06

5 Answers5

19

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)

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
2

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.

Steven Rands
  • 5,160
  • 3
  • 27
  • 56
1

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();
            }
        }
    }
}
Amir Saniyan
  • 13,014
  • 20
  • 92
  • 137
0

Extensions are associated in HKEY_CLASSES_ROOT key. So you need to open the registry and find the value you are interested in. You should also be able to find the default icon there.

Here's a sample project (I didn't try it).

Otávio Décio
  • 73,752
  • 17
  • 161
  • 228
  • 1
    you will not find such nice strings as "Control Panel Item" there – Andrey Sep 23 '10 at 15:47
  • The thing to note here is that extension associations will vary per machine. – Tony Abrams Sep 23 '10 at 15:50
  • Thankyou all. SHGetFileInfo seems a little less crude than registry manipulation. Also Andrey is write some extension are OK like PowerISO files but .cpl files are just called cplfiles instead of "Control Panel Items" as displayed in the default programs control panel within windows. Thankyou Thomas very helpful, also for anyone else who needs more reference in the future http://support.microsoft.com/kb/319350 shows how to use SHGetFileInfo in C# also. – Stewart Stoakes Sep 23 '10 at 15:55
0

Lets say your extension is .xyz To show most user friendly text like "Control Panel Item" you should do two things:

  1. Go to HKEY_CLASSES_ROOT and search for node xyzfile. Check for "cplfile"
  2. If it is not there you can get the association in the same place but node is .xyz . It will tell what app opens it so you can get the name.
Andrey
  • 59,039
  • 12
  • 119
  • 163