Получить тип файла в .NET.

Как я могу получить тип файла с помощью С#. например, если имя файла "abc.png" и тип файла будут "PNG Image" такими же, как и третий столбец "Тип" в проводнике окон.

Ответ 1

Вам нужно будет использовать API окон Функция SHGetFileInfo

В структуре вывода szTypeName содержится имя, которое вы ищете.

[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;
};

Обратите внимание, что это просто текущее "дружественное имя", которое хранится в реестре Windows, это всего лишь ярлык (но, вероятно, достаточно хорош для вашей ситуации).

Разница между szTypeName и szDisplayName описана в MSDN:

szTypeName: строка с нулевым завершением, которая описывает тип файла.

szDisplayName: строка с нулевым завершением который содержит имя файла как он появляется в оболочке Windows или путь и имя файла, который содержит значок, представляющий файл.

Для более точного определения типа файла вам нужно будет прочитать первый кусок байтов каждого файла и сравнить их с опубликованными спецификациями файлов. Для информации о форматах файлов см. Сайт Wotsit.

Связанная страница также содержит полный пример кода на С#.

Ответ 2

Вам понадобится P/Invoke для SHGetFileInfo, чтобы получить информацию о типе файла. Вот полный образец:

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);
    }
}

Ответ 3

P/вызывать SHGetFileInfo и проверять имя szDisplayName в возвращаемой структуре. Результат будет зависеть от того, как ваши типы файлов определены (т.е. Это не будет абсолютной ссылкой). Но в большинстве случаев это должно быть хорошо. Нажмите здесь, чтобы получить подпись С# SHGetFileInfo и пример кода на pinvoke.net (удивительный сайт, который он)

Для абсолютной ссылки вам понадобится что-то, что проверяет несколько байтов в двоичном заголовке и сравнивается с известным списком этих байтов. Я думаю, что по умолчанию это делают системы на основе unix.

Ответ 4

Функция Win-API SHGetFileInfo() - ваш друг. Посмотрите здесь для некоторых фрагментов кода.