直接呼叫 Windows Shell API,取得系統顯示的檔案類型描述 (如「Text Document」、「JPEG Image」),支援圖示、屬性等豐富資訊。
using System;
using System.Runtime.InteropServices;
public static class FileTypeHelper
{
// 結構對應 SHFILEINFO
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
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 enum SHGFI : uint
{
ICON = 0x100,
DISPLAYNAME = 0x200,
TYPENAME = 0x400,
ATTRIBUTES = 0x800,
ICONLOCATION = 0x1000,
EXETYPE = 0x2000,
SYSICONINDEX = 0x4000,
LINKOVERLAY = 0x8000,
SELECTED = 0x10000,
ATTR_SPECIFIED = 0x20000,
LARGEICON = 0x0,
SMALLICON = 0x1,
OPENICON = 0x2,
SHELLICONSIZE = 0x4,
PIDL = 0x8,
USEFILEATTRIBUTES = 0x10,
ADDOVERLAYS = 0x20,
OVERLAYINDEX = 0x40,
}
private enum FILE_ATTRIBUTE : uint
{
NORMAL = 0x80,
// 其他屬性略...
}
[DllImport("shell32.dll", CharSet = CharSet.Auto, EntryPoint = "SHGetFileInfo")]
private static extern IntPtr SHGetFileInfo(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbFileInfo,
uint uFlags);
///
/// 取得檔案類型描述 (如 "Text Document")
///
public static string GetTypeName(string filePath)
{
SHFILEINFO info = new SHFILEINFO();
IntPtr result = SHGetFileInfo(
filePath,
(uint)FILE_ATTRIBUTE.NORMAL,
ref info,
(uint)Marshal.SizeOf(info),
(uint)SHGFI.TYPENAME);
return result != IntPtr.Zero ? info.szTypeName : null;
}
///
/// 取得檔案關聯圖示 (大圖示)
///
public static Icon GetLargeIcon(string filePath)
{
SHFILEINFO info = new SHFILEINFO();
SHGetFileInfo(filePath, 0, ref info, (uint)Marshal.SizeOf(info),
(uint)(SHGFI.ICON | SHGFI.LARGEICON | SHGFI.USEFILEATTRIBUTES));
return info.hIcon != IntPtr.Zero ? Icon.FromHandle(info.hIcon) : null;
}
}
string type = FileTypeHelper.GetTypeName(@"C:\Windows\notepad.exe");
// 輸出: "Application" 或 "應用程式" (視系統語言)
Console.WriteLine(type);
Icon icon = FileTypeHelper.GetLargeIcon(@"test.pdf");
// 可直接指派給 PictureBox.Image 或儲存為 .ico
using Microsoft.Win32;
public static string GetTypeNameViaRegistry(string extension)
{
// 1. 取得 ProgID (如 ".txt" -> "txtfile")
using (RegistryKey extKey = Registry.ClassesRoot.OpenSubKey(extension))
{
if (extKey == null) return null;
string progId = extKey.GetValue(null)?.ToString();
if (string.IsNullOrEmpty(progId)) return null;
// 2. 取得友善名稱
using (RegistryKey progKey = Registry.ClassesRoot.OpenSubKey(progId))
{
return progKey?.GetValue(null)?.ToString();
}
}
}
| 維度 | SHGetFileInfo (Shell API) | 登錄表查詢 |
|---|---|---|
| 準確度 | 高 (反映 Shell 實際顯示) | 中 (依賴註冊表完整性) |
| 支援資訊 | 類型名、圖示、顯示名、屬性、exe 類型 | 僅類型名/ProgID |
| 效能 | 較慢 (跨進程 Shell 呼叫) | 快 (純登錄表讀取) |
| 相依性 | shell32.dll (Windows 內建) | 無額外相依 |
| 適用場景 | 檔案總管風格 UI、需圖示、需精確類型 | 簡易副檔名對應、批次處理、無 UI 執行緒 |
| 限制 | 需在 STA 執行緒 (UI 執行緒) 呼叫 | 若檔案關聯損壞或非標準註冊會失效 |
public static string GetMimeType(string extension)
{
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(extension))
{
return key?.GetValue("Content Type")?.ToString();
}
}
// 用法: GetMimeType(".pdf") -> "application/pdf"
mime.types 檔)。