查找用于在 Windows 上打开特定文件类型的默认应用程序
Posted
技术标签:
【中文标题】查找用于在 Windows 上打开特定文件类型的默认应用程序【英文标题】:Finding the default application for opening a particular file type on Windows 【发布时间】:2010-09-14 19:24:56 【问题描述】:我正在使用 C# 开发一个面向 .NET Framework 2.0 的应用程序,我需要能够找到用于打开特定文件类型的默认应用程序。
我知道,例如,如果您只想使用该应用程序打开一个文件,您可以使用以下内容:
System.Diagnostics.Process.Start( "C:\...\...\myfile.html" );
在默认浏览器中打开 HTML 文档,或
System.Diagnostics.Process.Start( "C:\...\...\myfile.txt" );
在默认文本编辑器中打开一个文本文件。
但是,我希望能够在默认文本编辑器中打开不一定具有 .txt 扩展名的文件(例如),所以我需要能够找到打开 .txt 文件的默认应用程序,这将允许我直接调用它。
我猜我需要 P/Invoke 一些 Win32 API 才能做到这一点,但是快速浏览一下 Google 和 MSDN 并没有发现任何有趣的东西;我确实找到了大量完全不相关的页面,但没有像我正在寻找的那样。
【问题讨论】:
【参考方案1】:您可以在注册表部分HKEY_CLASSES_ROOT
下查看扩展和操作详细信息。这方面的文档是on MSDN。或者,您可以使用IQueryAssociations 接口。
【讨论】:
在我看来,使用 FindExecutable 是更好的方式:***.com/a/9540278/2427749【参考方案2】:Here is a blog post with about this topic. 代码示例在 VB.net 中,但应该很容易将它们移植到 C#。
【讨论】:
我冒昧地将代码转换为 C# 并稍作修改:***.com/a/17773554/67824【参考方案3】:您可以只查询注册表。首先获取 HKEY_CLASSES_ROOT\.ext 下的 Default 条目
这会给你类名。例如 .txt 的默认值为 txtfile
然后打开HKEY_CLASSES_ROOT\txtfile\Shell\Open\Command
这将为您提供使用的默认命令。
【讨论】:
【参考方案4】:哇!当然。
HKEY_CLASSES_ROOT\.txt
包括对
的引用HKEY_CLASSES_ROOT\txtfile
其中包含一个子键
HKEY_CLASSES_ROOT\txtfile\shell\open\command
引用记事本。
已排序,非常感谢!
巴特
【讨论】:
这是%SystemRoot%\system32\NOTEPAD.EXE %1
。在我的情况下,这不是默认程序。此外,由于%SystemRoot%
文字和%1
,您不能使用Process.Start
。所有这些都需要在您的代码中进行特殊处理,无法完全&明确地涵盖,因为谁知道在这样的字符串中还能预期什么。【参考方案5】:
所有当前的答案都不可靠。注册表是一个实现细节,确实这样的代码在我的 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();
【讨论】:
这被否决了,但对我来说效果很好,只是做了一个小修复(上面编辑过)。您将需要“使用 System.Runtime.InteropServices”。我找不到枚举,所以从 MSDN 复制它们:ASSOCF 和 ASOCSTR。为了始终访问文本编辑器,我用 AssocStr.ASSOCSTR_EXECUTABLE 和“.txt”调用了这个方法。 我真的很喜欢并欣赏这个答案,但我也很难找到 AssocF 和 AssocStr 的参考资料。我最终在另一个堆栈溢出答案中找到了这些标志的实现:***.com/questions/770023/…Upvoted,谢谢! AssocStr.Executable 不适用于 .png 等图像扩展名。您如何解决他们的容器应用程序? 我今天遇到了这个 SO 问题,并且遇到了 @IngoB 与 .png 扩展名相同的问题。差异似乎源于扩展是由“完整” EXE 还是 UWP 处理(这仍然是他们所谓的,对 :) 应用程序......例如,在我的情况下,.png 由照片应用程序,因此虽然AssocStr.Executable
会失败,但请求AssocStr.AppId
会返回Microsoft.Windows.Photos_8wekyb3d8bbwe!App
。然后可以使用类似于此答案的代码运行:***.com/a/41906116
@pwrigshihanomoronimo 谢谢,已修复 WayBack Machine 链接并向 MS 提交了有关错误链接的反馈(在您提到的文档中单击 ASSOCF
时,我被引导到另一个枚举)。【参考方案6】:
一个迟到的答案,但有一个很好的 NUGET 包可以处理文件关联:文件关联
Link NUGET File Association
用法很简单,例如将所有允许的文件扩展名添加到上下文菜单:
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());
【讨论】:
以上是关于查找用于在 Windows 上打开特定文件类型的默认应用程序的主要内容,如果未能解决你的问题,请参考以下文章
linux查找当前目录下所有子目录特定文件类型需要查找的文件内容
仅针对特定文件类型将菜单项添加到 Windows 上下文菜单