How do I get File Type Information based on extension? (not MIME) in c#

后端 未结 5 1889
失恋的感觉
失恋的感觉 2020-12-01 12:23

How do I get the general File type description based on extension like Explorer does it? So not MIME but the information that the end-user sees, like.

.doc = Microso

相关标签:
5条回答
  • 2020-12-01 13:06

    Some extra if's for unknown file types in XP.. May not really give the right results when using it with anything but FriendlyDocName, but just as an example:

    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();
    }
    
    0 讨论(0)
  • 2020-12-01 13:15

    The good old FileSystemObject has this functionality built into it.

    If you don't mind using it then the following code is very short.

    Add a reference to Microsoft Scripting Runtime to your project and try this in a Windows Form app.

    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;
    }
    

    The getFileType creates a temporary file with the supplied extension, then with the FileSystemObject the file is opened and its Type is returned, which is the type description you want. The getSometypes writes them out in the Output window.

    In this case (in Swedish):

    Textdokument
    Microsoft Word 97–2003-dokument
    Microsoft Excel-kalkylblad
    
    0 讨论(0)
  • 2020-12-01 13:19

    My code that include check to prevent from some common errors... Hope it helps :-)

    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
            }
    
    
    
        }
    }
    
    0 讨论(0)
  • 2020-12-01 13:23

    Thanks Dan, Alright.. This answers the first question I had. Sadly not the second. Note: Not everything prints.. Credits to 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
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-01 13:25

    Reading stuff like this directly from the registry is generally a bad idea (see Raymond Chen's blog for all the gory details). In this particular case, the API you want is AssocQueryString in shlwapi.h.

    Here's C++ code:

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

    You can use this from C# either via C++/CLI exposing a nice .NET-friendly API; or call it directly via P/Invoke.

    0 讨论(0)
提交回复
热议问题