find在Windows上打开特定文件types的默认应用程序
我正在开发一个针对.NET Framework 2.0的应用程序,使用C#,我需要能够find用于打开特定文件types的默认应用程序。
我知道,例如,如果您只想使用该应用程序打开文件,则可以使用如下所示的内容:
System.Diagnostics.Process.Start( "C:\...\...\myfile.html" );
在默认浏览器中打开HTML文档,或者
System.Diagnostics.Process.Start( "C:\...\...\myfile.txt" );
在默认的文本编辑器中打开一个文本文件。
但是,我想要做的是在默认文本编辑器中打开不一定具有.txt扩展名(例如)的文件,因此我需要能够find打开的默认应用程序。 txt文件,这将允许我直接调用它。
我猜想有一些Win32 API需要P / Invoke才能做到这一点,但是Google和MSDN的快速浏览并没有透露任何有趣的东西; 我确实发现了大量完全不相关的页面,但没有像我期待的那样。 如果有人知道我应该使用哪种API /方法,我会很高兴听到你的消息。
非常感谢!
您可以在registry部分HKEY_CLASSES_ROOT
查看扩展和操作的详细信息。 此文档在MSDN上 。 或者,您可以使用IQueryAssociations接口。
目前所有的答案都不可靠。 registry是一个实现细节,事实上这样的代码在我的Windows 8.1机器上被破坏了。 正确的方法是使用Win32 API,特别是AssocQueryString :
using System.Runtime.InteropServices; [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)] public static extern uint AssocQueryString( AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, ref uint pcchOut ); [Flags] public enum AssocF { None = 0, 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, Init_IgnoreUnknown = 0x400, Init_Fixed_ProgId = 0x800, Is_Protocol = 0x1000, Init_For_File = 0x2000 } public enum AssocStr { Command = 1, Executable, FriendlyDocName, FriendlyAppName, NoOpen, ShellNewValue, DDECommand, DDEIfExec, DDEApplication, DDETopic, InfoTip, QuickTip, TileInfo, ContentType, DefaultIcon, ShellExtension, DropTarget, DelegateExecute, Supported_Uri_Protocols, ProgID, AppID, AppPublisher, AppIconReference, Max }
相关文件:
- AssocQueryString
- ASSOCF
- ASSOCSTR
示例用法:
static string AssocQueryString(AssocStr association, string extension) { const int S_OK = 0; const int S_FALSE = 1; uint length = 0; uint ret = AssocQueryString(AssocF.None, association, extension, null, null, ref length); if (ret != S_FALSE) { throw new InvalidOperationException("Could not determine associated string"); } var sb = new StringBuilder((int)length); // (length-1) will probably work too as the marshaller adds null termination ret = AssocQueryString(AssocF.None, association, extension, null, sb, ref length); if (ret != S_OK) { throw new InvalidOperationException("Could not determine associated string"); } return sb.ToString(); }
卫生署! 当然。
HKEY_CLASSES_ROOT\.txt
包括对…的引用
HKEY_CLASSES_ROOT\txtfile
其中包含一个子项
HKEY_CLASSES_ROOT\txtfile\shell\open\command
其中引用记事本。
分类,非常感谢!
巴特
这里是关于这个话题的博客文章。 代码示例在VB.net中,但应该很容易将它们移植到C#中。
你可以查询registry。 首先获取HKEY_CLASSES_ROOT \ .ext下的Default项
这将给你的类名。 例如,.txt有一个默认的txtfile
然后打开HKEY_CLASSES_ROOT \ txtfile \ Shell \ Open \ Command
这会给你使用默认的命令。
一个迟到的答案,但有一个好的NUGET包处理文件关联:文件关联
链接NUGET文件关联
用法很简单,例如将所有允许的文件扩展名添加到上下文菜单中:
private void OnMenuSourceFileOpening(object sender, ...) { // open a context menu with the associated files + ".txt" files if (File.Exists(this.SelectedFileName)) { string fileExt = Path.GetExtension(this.SelectedFileNames); string[] allowedExtensions = new string[] { fileExt, ".txt" }; var fileAssociations = allowedExtensions .Select(ext => new FileAssociationInfo(ext)); var progInfos = fileAssociations .Select(fileAssoc => new ProgramAssociationInfo (fileAssoc.ProgID)); var toolstripItems = myProgInfos .Select(proginfo => new ToolStripLabel (proginfo.Description) { Tag = proginfo }); // add also the prog info as Tag, for easy access // when the toolstrip item is selected // of course this can also be done in one long linq statement // fill the context menu: this.contextMenu1.Items.Clear(); this.contextMenuOpenSourceFile.Items.AddRange (toolstripItems.ToArray()); } }
您可以编写纯粹的C#代码来从registry中获取该信息。 这是获得注册申请的代码:
public static class Utils { public static bool TryGetRegisteredApplication(string extension, out string registeredApp) { string extensionId = GetClassesRootKeyDefaultValue(extension); if (extensionId == null) { registeredApp = null; return false; } string openCommand = GetClassesRootKeyDefaultValue( Path.Combine(new[] { extensionId, "shell", "open", "command" })); if (openCommand == null) { registeredApp = null; return false; } if (openCommand.Contains("\"")) { openCommand = openCommand.Split(new []{ "\""},StringSplitOptions.RemoveEmptyEntries)[0]; } else { openCommand = openCommand.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)[0]; } registeredApp = openCommand; return true; } private static string GetClassesRootKeyDefaultValue(string keyPath) { using (var key = Registry.ClassesRoot.OpenSubKey(keyPath)) { if (key == null) { return null; } var defaultValue = key.GetValue(null); if (defaultValue == null) { return null; } return defaultValue.ToString(); } } }
我从互联网上收集,然后改变一些代码,使其工作更好。
*注意:如果用rundll32运行应用程序,这个代码会出错,例如:C:\ Windows \ System32 \ rundll32.exe“C:\ Program Files(x86)\ Windows Photo Viewer \ PhotoViewer.dll”,ImageView_Fullscreen%1剪切C:\ Windows \ System32 \ rundll32.exe
我强烈build议不要使用registry值。 我注意到在我的Win 8.1上,registry并不总是将正确的编辑器报告给扩展。 例如,我将NotePad ++作为扩展名为“.txt”的文本编辑器,在Windows控制面板中也对此进行了默认应用。 但registryshell \打开\命令说错了,它是记事本(不是++)。 所以要注意。