【发布时间】:2010-11-29 01:44:16
【问题描述】:
如何使用 c# 获取文件类型。 例如,如果文件名 id “abc.png”和文件类型将“PNG Image”与窗口资源管理器中的第三列“Type”相同。
【问题讨论】:
如何使用 c# 获取文件类型。 例如,如果文件名 id “abc.png”和文件类型将“PNG Image”与窗口资源管理器中的第三列“Type”相同。
【问题讨论】:
您需要 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);
}
}
【讨论】:
您需要使用 Windows API SHGetFileInfo function
在输出结构中,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: 以 Null 结尾的字符串 描述文件的类型。
szDisplayName: 以 Null 结尾的字符串 包含文件的名称为 它出现在 Windows shell 中,或者 文件的路径和名称 包含代表 文件。
为了更准确地确定文件类型,您需要读取每个文件的第一个字节块并将其与已发布的文件规范进行比较。有关文件格式的信息,请参见 Wotsit 之类的网站。
链接页面还包含完整的示例 C# 代码。
【讨论】:
P/invoke 到SHGetFileInfo,并检查返回结构中的 szDisplayName。结果将取决于您如何定义文件类型(即它不是绝对参考)。但在大多数情况下应该没问题。 Click here for the c# signature of SHGetFileInfo and example code on pinvoke.net(真棒网站)
对于绝对引用,您需要检查二进制标头中的几个字节并与这些字节的已知列表进行比较 - 我认为这是基于 unix 的系统默认执行此操作的方式。
【讨论】:
Win-API 函数 SHGetFileInfo() 是您的朋友。查看 here 获取一些代码 sn-ps。
【讨论】:
如果您不想使用 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;
}
然后你可以使用扩展作为key来获取扩展的Registry数据:
string fileType = GetRegistryFileTypes()[Path.GetExtension(filePath)];
if (fileType != null && fileType.Length > 0)
// do whatever here
【讨论】: