[ACCEPTED]-Get file type in .NET-file

Accepted answer
Score: 21

You'll need to P/Invoke to SHGetFileInfo 2 to get file type information. Here is a 1 complete sample:

using System;
using System.Runtime.InteropServices;

static class NativeMethods
{
    [StructLayout(LayoutKind.Sequential)]
    public 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;
    };

    public static class FILE_ATTRIBUTE
    {
        public const uint FILE_ATTRIBUTE_NORMAL = 0x80;
    }

    public static class SHGFI
    {
        public const uint SHGFI_TYPENAME = 0x000000400;
        public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
    }

    [DllImport("shell32.dll")]
    public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
}

class Program
{
    public static void Main(string[] args)
    {
        NativeMethods.SHFILEINFO info = new NativeMethods.SHFILEINFO();

        string fileName = @"C:\Some\Path\SomeFile.png";
        uint dwFileAttributes = NativeMethods.FILE_ATTRIBUTE.FILE_ATTRIBUTE_NORMAL;
        uint uFlags = (uint)(NativeMethods.SHGFI.SHGFI_TYPENAME | NativeMethods.SHGFI.SHGFI_USEFILEATTRIBUTES);

        NativeMethods.SHGetFileInfo(fileName, dwFileAttributes, ref info, (uint)Marshal.SizeOf(info), uFlags);

        Console.WriteLine(info.szTypeName);
    }
}
Score: 11

You will need to use the windows API SHGetFileInfo function

In 18 the output structure, szTypeName contains the name 17 you are looking for.

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public 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;
};

Note that this is simply 16 the current "Friendly name" as 15 stored in the Windows Registry, it is just 14 a label (but is probably good enough for 13 your situation).

The difference between szTypeName 12 and szDisplayName is described at MSDN:

szTypeName: Null-terminated 11 string that describes the type of file.

szDisplayName: Null-terminated 10 string that contains the name of the file 9 as it appears in the Windows shell, or the 8 path and name of the file that contains 7 the icon representing the file.

For more 6 accurate determination of file type you 5 would need to read the first chunk of bytes 4 of each file and compare these against published 3 file specifications. See a site like Wotsit for 2 info on file formats.

The linked page also 1 contains full example C# code.

Score: 10

P/invoke to SHGetFileInfo, and check szDisplayName in 10 the returned structure. The result will 9 depend on how you have your file types defined 8 (i.e. it won't be an absolute reference). But 7 it should be fine in most cases. Click here for the c# signature of SHGetFileInfo and example code on pinvoke.net (awesome 6 site that it is)

For an absolute reference 5 you will need something that checks a few 4 bytes in the binary header and compares 3 against a known list of these bytes - I 2 think this is how unix-based systems do 1 it by default.

Score: 2

The Win-API function SHGetFileInfo() is 1 your friend. Look here for some code snippets.

Score: 1

If you do not want to use P/Invoke and rather 3 would like to look at the registry yourself:

private Dictionary<string, string> GetRegistryFileTypes()
{
  Dictionary<string, string> results = new Dictionary<string, string>();

  using (RegistryKey rootKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer\KindMap"))
    if (rootKey != null)
      foreach (string currSubKey in rootKey.GetValueNames())
        results.Add(currSubKey, rootKey.GetValue(currSubKey).ToString());

  return results;
}

Then 2 you can use the extension as a key to get 1 the Registry data for the extension:

string fileType = GetRegistryFileTypes()[Path.GetExtension(filePath)];

if (fileType != null && fileType.Length > 0)
  // do whatever here

More Related questions