首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 取得檔案類型描述:Shell API (SHGetFileInfo) 與登錄表兩種方法完整比較

     編輯:關於C語言

方法一:P/Invoke Shell32.dll SHGetFileInfo (推薦)

直接呼叫 Windows Shell API,取得系統顯示的檔案類型描述 (如「Text Document」、「JPEG Image」),支援圖示、屬性等豐富資訊。

完整 P/Invoke 宣告


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

方法二:登錄表查詢 (不需 P/Invoke,但有限制)


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 執行緒) 呼叫若檔案關聯損壞或非標準註冊會失效

進階:取得 MIME 類型 (Content Type)


public static string GetMimeType(string extension)
{
    using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(extension))
    {
        return key?.GetValue("Content Type")?.ToString();
    }
}
// 用法: GetMimeType(".pdf") -> "application/pdf"

最佳實務建議

  • UI 應用 (WinForms/WPF):**優先用 SHGetFileInfo**,結果最符合使用者預期。
  • 服務/背景工作/ASP.NET Core:**用登錄表或對照表**,避免 STA 執行緒與 Shell 相依問題。
  • 跨平台 (.NET Core Linux/macOS):**不可用 Shell API**,需維護自有副檔名→MIME/類型對照字典 (可內嵌 mime.types 檔)。
  • 大量檔案處理:快取 SHGetFileInfo 結果 (以副檔名為鍵),避免重複呼叫。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved