2009-04-20 12 views
16

Jak uzyskać ogólny opis typu pliku na podstawie rozszerzenia takiego jak Explorer? Więc nie MIME, ale informacje, które widzą użytkownicy końcowi.Jak uzyskać informacje o typie pliku na podstawie rozszerzenia? (nie MIME) w języku C#

.doc = Dokument Microsoft Office Word 97 - 2003 Dokument .zip = Plik ZIP .avi = Plik wideo.

Jak mogę uzyskać informacje "drugorzędne", które wydają się być dostępne, co chyba nie jest oparte na rozszerzeniu. Podobnie jak w przypadku "Plików wideo", może dać ci "Długość" filmu lub na plikach doc, ile stron ma itd. Itd.

Odpowiedz

26

Dzięki Dan, Dobra .. To odpowiada na pierwsze pytanie, które miałem. Niestety nie drugi. Uwaga: wydruki nie wszystko .. kredytów 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

myślę swoje dwa pytania są raczej niezwiązane. –

4

Czytanie takich rzeczy bezpośrednio z rejestru jest generalnie złym pomysłem (patrz Raymond Chen's blog dla wszystkich gory details). W tym konkretnym przypadku wymagany interfejs API to AssocQueryString w shlwapi.h.

Oto kod C++:

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

Możesz użyć tego od C# albo poprzez C++/CLI odsłaniając piękny przyjazny .NET API; lub zadzwoń bezpośrednio przez P/Invoke.

3

Niektóre dodatkowe jeśli dla nieznanych typów plików w XP .. Może naprawdę nie dają odpowiednich wyników podczas używania go z niczego, ale FriendlyDocName, ale po prostu jako przykład :

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

Dobrze zrobione Pjanssen, właśnie dowiedziałem się, że oryginalna funkcja nie działa w XP! Dobra robota, zaoszczędziło mi czas, że muszę to zrobić sam! – JustAPleb

3

mój kod, który to sprawdzić aby uniknąć pewnych typowych błędów ... nadzieję, że pomoże :-)

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 
     } 



    } 
}