2012-11-19 11 views
2

我想弄清楚用于打开给定扩展名的文件的可执行文件,所以如果扩展名没有,可以显示该可执行文件的图标。如何在Windows上正确检索与扩展相关联的打开命令?

我知道在文件类型的HKEY_CLASSES_ROOT注册表项中的打开动词,但我发现它的值并不总是正确的。

例如,我目前在OS X上的Parallels中运行Windows .PDF文件的默认关联是Safari。我通过浏览器将默认关联更改为Adobe Reader。注册表中的开放式动词仍然是Safari,但是当我双击一个PDF文件时,它会用Adobe Reader打开。 32位和64位注册表都具有相同的值。

有没有更好的方式来检索文件类型的关联,要么与.NET或WINAPI?

+0

最大的问题是,有“类”的文件类型,然后有扩展名。它们可以以各种方式组合。 – 0xC0000022L

+0

是否有某种.NET函数或winapi调用可以解决这个问题? –

+0

看到我的答案。我在.NET世界中并不在家,但我在回答中给出了一些指示,这可能会帮助您找到所描述的Win32/Shell API的现有.NET类。 – 0xC0000022L

回答

2

最好的办法可能是使用Assoc*功能组,如AssocQueryKey()AssocQueryString()via PInvoke。然而,我不知道.NET框架中的许多类中的其中一个是否已经为你包装了。但是Shell API提供了一个选项来检索这些信息。

另请注意,注释部分指出上述函数是IQueryAssociations接口的包装器,这使得您更有可能在.NET中拥有另一条更直的路线。

旧式功能是这样的:FindExecutable()。不过,不要使用它。它使用与ShellExecute()相同的错误代码。

还看到答案为Windows: List and Launch applications associated with an extension

-1

您还需要检查HKEY_USERS \ {User} \ Software \ Classes。用户可以覆盖自己的默认应用程序。

+0

注册表中的HKEY_USERS \ {guid} _CLASSES和HKEY_USERS \ {guid} \ Software \ Classes关键字具有旧的(也是不正确的)关联。 –

0

我的代码,其中包括检查一些常见的错误,以防止...希望这有助于:-)

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"); 
    /// Usage: string command FileAssociation.GetExecCommandAssociatedToExtension(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 GetExecCommandAssociatedToExtension(string ext, string verb = null) 
     { 
      if (ext[0] != '.') 
      { 
       ext = "." + ext; 
      } 

      string executablePath = FileExtentionInfo(AssocStr.Command, ext, verb); 

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

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



    } 
} 
相关问题