查找在 Windows 上打开特定文件类型的默认应用程序
题
我正在使用 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 并没有发现任何有趣的东西;我确实找到了大量完全不相关的页面,但没有像我正在寻找的那样。
解决方案
您可以在注册表部分 HKEY_CLASSES_ROOT
下查看扩展和操作详情。有关此文档的文档是在MSDN上。或者,您可以使用 IQueryAssociations 界面。
其他提示
目前所有的答案都是不可靠的。注册表是一个实现细节,实际上这样的代码在我的 Windows 8.1 机器上被破坏了。执行此操作的正确方法是使用 Win32 API,特别是 关联查询字符串:
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
}
相关文档:
使用示例:
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#应该很容易。
您只需查询注册表即可。首先获取HKEY_CLASSES_ROOT \ .ext
下的默认条目这将为您提供类名。例如.txt的默认值为txtfile
然后打开HKEY_CLASSES_ROOT \ txtfile \ Shell \ Open \ Command
这将为您提供使用的默认命令。
迟到的答案,但有一个很好的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());
}
}