【问题标题】:How do I get File Type Information based on extension? (not MIME) in c#如何根据扩展名获取文件类型信息? (不是 MIME)在 C#
【发布时间】:2010-10-20 16:18:45
【问题描述】:

我如何像 Explorer 一样获得基于扩展名的一般文件类型描述?所以不是 MIME,而是最终用户看到的信息,比如。

.doc = Microsoft Office Word 97 - 2003 文档 .zip = 压缩文件 .avi = 视频文件。

我怎样才能获得似乎可用的“辅助”信息,我猜它不是基于扩展的。就像在“视频文件”上一样,它可以为您提供电影的“长度”或在 doc 文件上它有多少页......等等......

【问题讨论】:

    标签: c# file mime file-type


    【解决方案1】:

    旧的 FileSystemObject 内置了这个功能。

    如果你不介意使用它,那么下面的代码很短。

    向您的项目添加对 Microsoft Scripting Runtime 的引用并在 Windows 窗体应用程序中尝试此操作。

    private void Form1_Load(object sender, EventArgs e) {
      getSometypes();
    }
    private void getSometypes()
    {
      System.Diagnostics.Debug.WriteLine(getFileType(".txt"));
      System.Diagnostics.Debug.WriteLine(getFileType(".doc"));
      System.Diagnostics.Debug.WriteLine(getFileType(".xlsx"));
    }    
    private string getFileType(object ext)
    {
      Scripting.FileSystemObject fso = new Scripting.FileSystemObject();
      string tempPath = System.IO.Path.GetTempPath();
      string tempFile = "";
      tempFile = tempPath + "tmp" + ext;
      System.IO.File.WriteAllText(tempFile, "");
      var f = fso.GetFile(tempFile);
      string t = f.Type;
      f.Delete();
      return t;
    }
    

    getFileType 使用提供的扩展名创建一个临时文件,然后使用 FileSystemObject 打开文件并返回其类型,这是您想要的类型描述。 getSometypes 将它们写在输出窗口中。

    在这种情况下(瑞典语):

    文本文件 Microsoft Word 97–2003 文档 Microsoft Excel-烷基白板

    【讨论】:

      【解决方案2】:

      我的代码包括检查以防止一些常见错误...希望它有所帮助:-)

      using System;
      using System.Diagnostics;
      using System.IO;
      using System.Runtime.InteropServices;
      using System.Text;
      
      namespace HQ.Util.Unmanaged
      {
          /// <summary>
          /// Usage:  string executablePath = FileAssociation.GetExecFileAssociatedToExtension(pathExtension, "open");
          /// </summary>
          public static class FileAssociation
          {
              /// <summary>
              /// 
              /// </summary>
              /// <param name="ext"></param>
              /// <param name="verb"></param>
              /// <returns>Return null if not found</returns>
              public static string GetExecFileAssociatedToExtension(string ext, string verb = null)
              {
                  if (ext[0] != '.')
                  {
                      ext = "." + ext;
                  }
      
                  string executablePath = FileExtentionInfo(AssocStr.Executable, ext, verb); // Will only work for 'open' verb
                  if (string.IsNullOrEmpty(executablePath))
                  {
                      executablePath = FileExtentionInfo(AssocStr.Command, ext, verb); // required to find command of any other verb than 'open'
      
                      // Extract only the path
                      if (!string.IsNullOrEmpty(executablePath) && executablePath.Length > 1) 
                      {
                          if (executablePath[0] == '"')
                          {
                              executablePath = executablePath.Split('\"')[1];
                          }
                          else if (executablePath[0] == '\'')
                          {
                              executablePath = executablePath.Split('\'')[1];
                          }
                      }
                  }
      
                  // Ensure to not return the default OpenWith.exe associated executable in Windows 8 or higher
                  if (!string.IsNullOrEmpty(executablePath) && File.Exists(executablePath) &&
                      !executablePath.ToLower().EndsWith(".dll"))
                  {
                      if (executablePath.ToLower().EndsWith("openwith.exe"))
                      {
                          return null; // 'OpenWith.exe' is th windows 8 or higher default for unknown extensions. I don't want to have it as associted file
                      }
                      return executablePath;
                  }
                  return executablePath;
              }
      
              [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
              static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, [In][Out] ref uint pcchOut);
      
              private static string FileExtentionInfo(AssocStr assocStr, string doctype, string verb)
              {
                  uint pcchOut = 0;
                  AssocQueryString(AssocF.Verify, assocStr, doctype, verb, null, ref pcchOut);
      
                  Debug.Assert(pcchOut != 0);
                  if (pcchOut == 0)
                  {
                      return "";
                  }
      
                  StringBuilder pszOut = new StringBuilder((int)pcchOut);
                  AssocQueryString(AssocF.Verify, assocStr, doctype, verb, pszOut, ref pcchOut);
                  return pszOut.ToString();
              }
      
              [Flags]
              public enum AssocF
              {
                  Init_NoRemapCLSID = 0x1,
                  Init_ByExeName = 0x2,
                  Open_ByExeName = 0x2,
                  Init_DefaultToStar = 0x4,
                  Init_DefaultToFolder = 0x8,
                  NoUserSettings = 0x10,
                  NoTruncate = 0x20,
                  Verify = 0x40,
                  RemapRunDll = 0x80,
                  NoFixUps = 0x100,
                  IgnoreBaseClass = 0x200
              }
      
              public enum AssocStr
              {
                  Command = 1,
                  Executable,
                  FriendlyDocName,
                  FriendlyAppName,
                  NoOpen,
                  ShellNewValue,
                  DDECommand,
                  DDEIfExec,
                  DDEApplication,
                  DDETopic
              }
      
      
      
          }
      }
      

      【讨论】:

      • 谢谢您,先生!这应该得到极大的支持,它立即起作用并且就像一个魅力,而许多其他答案并不是一个完整的解决方案。这将所有内容都放在了一个准备就绪的课程中,并立即生效。
      【解决方案3】:

      一些额外的 if's 用于 XP 中的未知文件类型。 将其与除了 FriendlyDocName 之外的任何内容一起使用时,可能不会真正给出正确的结果,但仅作为示例:

      public static string FileExtentionInfo(AssocStr assocStr, string doctype)
      {
         if ((doctype.Length <= 1) || !doctype.StartsWith(".")) return "";
      
         uint pcchOut = 0;
         AssocQueryString(AssocF.Verify, assocStr, doctype, null, null, ref pcchOut);
      
         if (pcchOut == 0) return (doctype.Trim('.').ToUpper() + " File");
      
         StringBuilder pszOut = new StringBuilder((int)pcchOut);
         AssocQueryString(AssocF.Verify, assocStr, doctype, null, pszOut, ref pcchOut);
         return pszOut.ToString();
      }
      

      【讨论】:

      • 干得好Pjanssen,我刚刚发现原来的功能在XP中不起作用!干得好,节省了我自己动手的时间!
      【解决方案4】:

      谢谢丹,好的。这回答了我的第一个问题。可惜不是第二个。注意:并非所有内容都打印出来。 感谢PInvoke.net

      using System;
      using System.Runtime.InteropServices;
      using System.Text;
      using System.Diagnostics;
      
      
      namespace WindowsFormsApplication1
      {
          static class Program
          {
              [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
              static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, [In][Out] ref uint pcchOut);
      
              /// <summary>
              /// The main entry point for the application.
              /// </summary>
              [STAThread]
              static void Main()
              {
                  Debug.WriteLine(FileExtentionInfo(AssocStr.Command, ".doc"), "Command");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.DDEApplication, ".doc"), "DDEApplication");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.DDEIfExec, ".doc"), "DDEIfExec");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.DDETopic, ".doc"), "DDETopic");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.Executable, ".doc"), "Executable");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.FriendlyAppName, ".doc"), "FriendlyAppName");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.FriendlyDocName, ".doc"), "FriendlyDocName");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.NoOpen, ".doc"), "NoOpen");
                  Debug.WriteLine(FileExtentionInfo(AssocStr.ShellNewValue, ".doc"), "ShellNewValue");
      
                  //  DDEApplication: WinWord
                  //DDEIfExec: Ñﻴ߾
                  //  DDETopic: System
                  //  Executable: C:\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE
                  //  FriendlyAppName: Microsoft Office Word
                  //  FriendlyDocName: Microsoft Office Word 97 - 2003 Document
      
      
              }
      
              public static string FileExtentionInfo(AssocStr assocStr, string doctype)
              {
                  uint pcchOut = 0;
                  AssocQueryString(AssocF.Verify, assocStr, doctype, null, null, ref pcchOut);
      
                  StringBuilder pszOut = new StringBuilder((int)pcchOut);
                  AssocQueryString(AssocF.Verify, assocStr, doctype, null, pszOut, ref pcchOut);
                  return pszOut.ToString();
              }
      
              [Flags]
              public enum AssocF
              {
                  Init_NoRemapCLSID = 0x1,
                  Init_ByExeName = 0x2,
                  Open_ByExeName = 0x2,
                  Init_DefaultToStar = 0x4,
                  Init_DefaultToFolder = 0x8,
                  NoUserSettings = 0x10,
                  NoTruncate = 0x20,
                  Verify = 0x40,
                  RemapRunDll = 0x80,
                  NoFixUps = 0x100,
                  IgnoreBaseClass = 0x200
              }
      
              public enum AssocStr
              {
                  Command = 1,
                  Executable,
                  FriendlyDocName,
                  FriendlyAppName,
                  NoOpen,
                  ShellNewValue,
                  DDECommand,
                  DDEIfExec,
                  DDEApplication,
                  DDETopic
              }
      
          }
      }
      

      【讨论】:

        【解决方案5】:

        直接从注册表中读取此类内容通常是个坏主意(请参阅Raymond Chen's blog 了解所有gory details)。在这种特殊情况下,您需要的 API 是 shlwapi.h 中的 AssocQueryString

        这是 C++ 代码:

        TCHAR buf[1024];
        DWORD sz = sizeof(buf) / sizeof(TCHAR);
        AssocQueryString(ASSOCF_INIT_DEFAULTTOSTAR, ASSOCSTR_FRIENDLYDOCNAME, L".sql", NULL, buf, &sz);
        

        您可以通过 C++/CLI 在 C# 中使用它,从而公开一个对 .NET 友好的 API;或直接通过P/Invoke调用。

        【讨论】:

          猜你喜欢
          • 2013-05-24
          • 2010-11-05
          • 2011-05-27
          • 2013-02-08
          • 2014-06-14
          • 2018-10-16
          相关资源
          最近更新 更多