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

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

11 голосов
/ 17 сентября 2009

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

Ответы [ 5 ]

20 голосов
/ 17 сентября 2009

Вам потребуется 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);
    }
}
11 голосов
/ 17 сентября 2009

Вам нужно будет использовать Windows 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 .

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

10 голосов
/ 17 сентября 2009

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

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

2 голосов
/ 17 сентября 2009

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

0 голосов
/ 12 февраля 2019

Если вы не хотите использовать P / Invoke и скорее хотите посмотреть реестр самостоятельно:

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

Затем вы можете использовать расширение в качестве ключа для получения данных реестра для расширения:

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

if (fileType != null && fileType.Length > 0)
  // do whatever here
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...