C# 在 .NET 中获取文件类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1437382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 16:32:19  来源:igfitidea点击:

Get file type in .NET

c#.netfile

提问by Firoz

How can i get type of file using c#. for example if a file name id "abc.png" and type of file will "PNG Image" same as third column "Type" in window explorer.

如何使用 c# 获取文件类型。例如,如果文件名 ID“abc.png”和文件类型将“PNG图像”与窗口资源管理器中的第三列“类型”相同。

采纳答案by Ash

You will need to use the windows API SHGetFileInfo function

您将需要使用 windows API SHGetFileInfo 函数

In the output structure, szTypeNamecontains the name you are looking for.

在输出结构中,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;
};

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

请注意,这只是存储在 Windows 注册表中的当前“友好名称”,它只是一个标签(但对于您的情况可能已经足够了)。

The difference between szTypeName and szDisplayName is described at MSDN:

MSDN 上描述了 szTypeName 和 szDisplayName 之间的区别:

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

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

szTypeName:描述文件类型的空终止字符串。

szDisplayName:以空字符结尾的字符串,其中包含文件在 Windows shell 中出现的名称,或者包含代表文件的图标的文件的路径和名称。

For more accurate determination of file type you would need to read the first chunk of bytes of each file and compare these against published file specifications. See a site like Wotsitfor info on file formats.

为了更准确地确定文件类型,您需要读取每个文件的第一个字节块,并将它们与已发布的文件规范进行比较。有关文件格式的信息,请参阅Wotsit 等网站。

The linked page also contains full example C# code.

链接页面还包含完整的示例 C# 代码。

回答by Dale

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

P/invoke 到SHGetFileInfo,并检查返回结构中的 szDisplayName 。结果将取决于您如何定义文件类型(即它不会是绝对引用)。但在大多数情况下应该没问题。单击此处获取 SHGetFileInfo 的 c# 签名和 pinvoke.net 上的示例代码(它是一个很棒的站点)

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

对于绝对引用,您需要检查二进制标头中的几个字节并与这些字节的已知列表进行比较 - 我认为这就是基于 unix 的系统默认情况下的做法。

回答by Frank Bollack

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

Win-API 函数 SHGetFileInfo() 是您的朋友。看看这里的一些代码片断。

回答by bobbymcr

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

您需要 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);
    }
}

回答by RooiWillie

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

如果您不想使用 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;
}

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

然后你可以使用扩展作为键来获取扩展的注册表数据:

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

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