如何在 .NET 中获取文件扩展名的描述
Posted
技术标签:
【中文标题】如何在 .NET 中获取文件扩展名的描述【英文标题】:How can I get the description of a file extension in .NET 【发布时间】:2011-04-16 08:29:11 【问题描述】:嗨,
Windows 提供文件扩展名的描述,例如 .cpl 文件的“控制面板项”和 .daa 文件的“PowerISO 文件”。有什么方法可以在 .NET 中获取这些数据?我使用 C#,但可以阅读所有其他 .NET 语言。还有一种方法可以获得扩展的默认图标吗?任何帮助将不胜感激。
提前致谢
【问题讨论】:
非常类似于***.com/questions/1910097/content-type-by-extension @David Stratton,这不是同一个问题。您提到的问题是关于获取内容类型(MIME 类型)。这是关于获取文件类型的描述。 Get file type in .NET的可能重复 【参考方案1】:您可以使用SHGetFileInfo
API 来获取该信息。这是一个包装器方法:
public static string GetFileTypeDescription(string fileNameOrExtension)
SHFILEINFO shfi;
if (IntPtr.Zero != SHGetFileInfo(
fileNameOrExtension,
FILE_ATTRIBUTE_NORMAL,
out shfi,
(uint)Marshal.SizeOf(typeof(SHFILEINFO)),
SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME))
return shfi.szTypeName;
return null;
[DllImport("shell32")]
private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags);
[StructLayout(LayoutKind.Sequential)]
private 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;
private const uint FILE_ATTRIBUTE_READONLY = 0x00000001;
private const uint FILE_ATTRIBUTE_HIDDEN = 0x00000002;
private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
private const uint FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
private const uint FILE_ATTRIBUTE_DEVICE = 0x00000040;
private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
private const uint FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
private const uint FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
private const uint FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
private const uint FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
private const uint FILE_ATTRIBUTE_OFFLINE = 0x00001000;
private const uint FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
private const uint FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
private const uint FILE_ATTRIBUTE_VIRTUAL = 0x00010000;
private const uint SHGFI_ICON = 0x000000100; // get icon
private const uint SHGFI_DISPLAYNAME = 0x000000200; // get display name
private const uint SHGFI_TYPENAME = 0x000000400; // get type name
private const uint SHGFI_ATTRIBUTES = 0x000000800; // get attributes
private const uint SHGFI_ICONLOCATION = 0x000001000; // get icon location
private const uint SHGFI_EXETYPE = 0x000002000; // return exe type
private const uint SHGFI_SYSICONINDEX = 0x000004000; // get system icon index
private const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon
private const uint SHGFI_SELECTED = 0x000010000; // show icon in selected state
private const uint SHGFI_ATTR_SPECIFIED = 0x000020000; // get only specified attributes
private const uint SHGFI_LARGEICON = 0x000000000; // get large icon
private const uint SHGFI_SMALLICON = 0x000000001; // get small icon
private const uint SHGFI_OPENICON = 0x000000002; // get open icon
private const uint SHGFI_SHELLICONSIZE = 0x000000004; // get shell size icon
private const uint SHGFI_PIDL = 0x000000008; // pszPath is a pidl
private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute
(大多数常量实际上并没有在该代码中使用,但我还是把它们放在了以防你想让代码适应你的特定需求)
【讨论】:
这与在 c# 中使用 FileInfo 类有何不同或更好? (只是好奇) @Tony Abrams,FileInfo 类没有给你类型描述。否则,我认为它主要是 SHFILEINFO 的包装器......using System.Runtime.InteropServices;
需要【参考方案2】:
为了使用SHGetFileInfo
,该文件必须存在于磁盘上。如果您只有文件的名称,甚至只有扩展名,则需要直接从注册表中获取信息:
public static string GetFileTypeDisplayName(string extension) =>
Registry.ClassesRoot.OpenSubKey(extension)?.GetValue(null) is string keyName ?
Registry.ClassesRoot.OpenSubKey(keyName)?.GetValue(null) as string :
null;
如果注册表中没有适合给定文件扩展名的条目,此方法将简单地返回 null
。
【讨论】:
【参考方案3】:您可以像这样搜索注册表:
在HKEY_CLASSES_ROOT
中搜索扩展名的默认值。例如HKEY_CLASSES_ROOT\.txt
的默认值为txtfile
。
然后搜索上一个结果的默认值:例如HKEY_CLASSES_ROOT\txtfile
的默认值是Text Document
。
经过两次搜索,答案是文本文档。
您可以通过RegEdit
测试任何其他扩展。
访问此链接:http://www.codeproject.com/KB/cs/GetFileTypeAndIcon.aspx?display=Print
这是这两个搜索的实现:
public static class Helper
public static string GetFileDescription(string fileName)
if (fileName == null)
throw new ArgumentNullException("fileName");
RegistryKey registryKey1 = null;
RegistryKey registryKey2 = null;
try
FileInfo fileInfo = new FileInfo(fileName);
if (string.IsNullOrEmpty(fileInfo.Extension))
return string.Empty;
string extension = fileInfo.Extension.ToLowerInvariant();
registryKey1 = Registry.ClassesRoot.OpenSubKey(extension);
if (registryKey1 == null)
return string.Empty;
object extensionDefaultObject = registryKey1.GetValue(null);
if (!(extensionDefaultObject is string))
return string.Empty;
string extensionDefaultValue = (string)extensionDefaultObject;
registryKey2 = Registry.ClassesRoot.OpenSubKey(extensionDefaultValue);
if (registryKey2 == null)
return string.Empty;
object fileDescriptionObject = registryKey2.GetValue(null);
if (!(fileDescriptionObject is string))
return string.Empty;
string fileDescription = (string)fileDescriptionObject;
return fileDescription;
catch (Exception)
return null;
finally
if (registryKey2 != null)
registryKey2.Close();
if (registryKey1 != null)
registryKey1.Close();
【讨论】:
【参考方案4】:扩展在 HKEY_CLASSES_ROOT 键中关联。所以你需要打开注册表,找到你感兴趣的值。你应该也可以在那里找到默认的图标。
Here 是一个示例项目(我没有尝试过)。
【讨论】:
你不会在那里找到像“控制面板项目”这样好的字符串 这里要注意的是扩展关联会因机器而异。 谢谢大家。 SHGetFileInfo 似乎没有注册表操作那么粗糙。 Andrey 还写了一些扩展名,就像 PowerISO 文件一样,但 .cpl 文件只是称为 cplfiles,而不是 Windows 内默认程序控制面板中显示的“控制面板项目”。谢谢Thomas 非常有帮助,对于将来需要更多参考的其他人support.microsoft.com/kb/319350 也展示了如何在 C# 中使用 SHGetFileInfo。【参考方案5】:假设您的扩展名是 .xyz 要显示大多数用户友好的文本,例如“控制面板项”,您应该做两件事:
-
转到 HKEY_CLASSES_ROOT 并搜索节点 xyzfile。检查“cplfile”
如果不存在,您可以在同一个地方获得关联,但节点是 .xyz 。它会告诉您打开它的应用程序,以便您获取名称。
【讨论】:
以上是关于如何在 .NET 中获取文件扩展名的描述的主要内容,如果未能解决你的问题,请参考以下文章
使用 .NET,如何根据文件签名而不是扩展名找到文件的 mime 类型
使用 .NET,如何根据文件签名而不是扩展名找到文件的 mime 类型
使用 .NET,如何根据文件签名而不是扩展名找到文件的 mime 类型