2010-09-23 50 views
4

HI,我怎樣才能在.NET中的文件擴展名的描述

Windows提供的說明了文件擴展名,如「控制面板項目」的.cpl文件和「PowerISO文件」爲.daa文件。有什麼辦法可以在.NET中獲得這些數據嗎?我使用C#,但可以閱讀所有其他的.NET語言。還有一種方法可以獲取擴展的默認圖標嗎?任何幫助,將不勝感激。

在此先感謝

+0

非常相似http://stackoverflow.com/questions/1910097/content-type-by-extension – David 2010-09-23 15:47:11

+0

@David Stratton,這不是同一個問題。你提到的問題是關於獲取內容類型(MIME類型)。這個是關於獲取文件類型的描述。 – 2010-09-23 15:51:52

+1

[在.NET中獲取文件類型]的可能的重複(http://stackoverflow.com/questions/1437382/get-file-type-in​​-net) – 2010-09-23 16:06:07

回答

10

您可以使用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 

(大部分常量實際上並沒有在代碼中使用,但我把它們反正如果你想要的代碼適應你的特定需求)

+1

這是如何更好或不同於在C#中使用FileInfo類? (只是好奇) – 2010-09-23 15:57:18

+0

@Tony艾布拉姆斯,FileInfo類不會給你類型的描述。否則,我認爲它主要是SHFILEINFO的包裝... – 2010-09-23 16:20:21

+1

'使用System.Runtime.InteropServices;'需要 – 2016-05-28 19:21:16

0

擴展名在HKEY_CLASSES_ROOT鍵中關聯。因此,您需要打開註冊表並找到您感興趣的值。您還應該能夠在其中找到默認圖標。

Here是一個示例項目(我沒有嘗試過)。

+1

您不會在那裏找到如「控制面板項目」那樣漂亮的字符串 – Andrey 2010-09-23 15:47:10

+0

這裏需要注意的是,擴展關聯會因機器而異。 – 2010-09-23 15:50:01

+0

謝謝全部。SHGetFileInfo似乎沒有註冊表操作那麼簡單。 Andrey還寫了一些擴展名,比如PowerISO文件,但.cpl文件只是被稱爲cplfiles,而不是「控制面板項目」,如窗口中默認程序控制面板中顯示的那樣。 Thankyou Thomas非常有幫助,對於將來需要更多參考的人也是如此http://support.microsoft.com/kb/319350顯示瞭如何在C#中使用SHGetFileInfo。 – 2010-09-23 15:55:05

0

比方說您的擴展名爲.xyz要顯示用戶最友好的文本,如「控制面板項」你應該做兩件事情:

  1. 轉到HKEY_CLASSES_ROOT和搜索節點xyzfile。檢查「cplfile」
  2. 如果不存在,則可以在同一位置獲得關聯,但節點爲.xyz。它會告訴什麼應用程序打開它,所以你可以得到的名字。
0

您可以搜索這樣的註冊表:在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(); 
      } 
     } 
    } 
}