¿Cómo puedo obtener información del fichero de tipo basado en la extensión? (No MIME) en c #

StackOverflow https://stackoverflow.com/questions/770023

  •  12-09-2019
  •  | 
  •  

Pregunta

¿Cómo consigo la descripción Tipo de archivo general basada en la extensión como el Explorador lo hace? Así que no MIME pero la información que el usuario final ve, al igual que.

.doc = Microsoft Office Word 97 - documento de 2003 .zip = ZIP File .avi = archivo de vídeo.

Y cómo puedo obtener la información 'secundario' que parece estar disponible, lo que supongo que no es a base de extensión. Al igual que en "archivos de vídeo" se le puede dar la 'longitud' de la película o en archivos doc cuántas páginas tiene .. etc etc ..

¿Fue útil?

Solución

Gracias Dan, bien .. Esto responde a la primera pregunta que tenía. Lamentablemente no el segundo. Nota: No todo impresiones .. Créditos a 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
        }

    }
}

Otros consejos

Mi código que incluye verificación para evitar algunos de los errores comunes ... Espero que ayuda: -)

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
        }



    }
}

material de lectura como esto directamente desde el registro es generalmente una mala idea (ver Raymond Chen el blog de todo el detalles morbosos ). En este caso particular, la API que quiere es AssocQueryString en shlwapi.h .

Aquí está el código de C ++:

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

Puede utilizar esto desde C #, ya sea a través de C ++ / CLI exponer un buen API .NET ambiente; o llamar directamente a través de P / Invoke .

Algunos extra si es para tipos de archivos desconocidos en XP .. en realidad no puede dar los resultados deseados cuando se utiliza con cualquier cosa, pero FriendlyDocName, pero sólo como un ejemplo:

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();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top