如何将文件扩展名关联到C#中的当前可执行文件

我想将文件扩展名关联到C#中的当前可执行文件。 这样,当用户在资源管理器中点击文件时,它将以给定的文件作为第一个参数运行我的可执行文件。 理想情况下,它也将给定文件扩展名的图标设置为我的可执行文件的图标。 谢谢大家。

似乎没有一个用于直接管理文件关联的.Net API,但可以使用Registry类来读取和写入所需的密钥。

您需要在HKEY_CLASSES_ROOT下创建一个名称设置为您的文件扩展名(例如:“.txt”)的密钥。 将此键的默认值设置为文件类型的唯一名称,例如“Acme.TextFile”。 然后在名称设置为“Acme.TextFile”的HKEY_CLASSES_ROOT下创建另一个键。 添加一个名为“DefaultIcon”的子项,并将该项的默认值设置为包含您希望用于此文件类型的图标的文件。 添加另一个名为“shell”的兄弟。 在“shell”键下面,通过资源管理器上下文菜单为每一个你想要的操作添加一个键,将每个键的默认值设置为可执行文件的路径,后跟一个空格,“%1”表示路径到选中的文件。

例如,下面是一个示例注册表文件,用于在.txt文件和EmEditor之间创建关联:

 Windows注册表编辑器版本5.00

 [HKEY_CLASSES_ROOT \ .TXT]
 @ = “emeditor.txt”

 [HKEY_CLASSES_ROOT \ emeditor.txt]
 @ =“文本文档”

 [HKEY_CLASSES_ROOT \ emeditor.txt \的DefaultIcon]
 @ = “%SYSTEMROOT%\\ SYSWOW64 \\ imageres.dll,-102”

 [HKEY_CLASSES_ROOT \ emeditor.txt \壳]

 [HKEY_CLASSES_ROOT \ emeditor.txt \壳\开放]

 [HKEY_CLASSES_ROOT \ emeditor.txt \壳\开放\命令]
 @ =“\”C:\\ Program Files \\ EmEditor \\ EMEDITOR.EXE \“\”%1 \“”

 [HKEY_CLASSES_ROOT \ emeditor.txt \壳\打印]

 [HKEY_CLASSES_ROOT \ emeditor.txt \壳\打印\命令]
 @ =“\”C:\\ Program Files \\ EmEditor \\ EMEDITOR.EXE \“/ p \”%1 \“”

另外,如果您决定使用注册表方式,请记住当前用户关联在HKEY_CURRENT_USER \ Software \ Classes下 。 把你的应用程序添加到本地机器类可能会更好。

如果您的程序将由有限的用户运行,您将无法修改CLASSES_ROOT。

如果您使用ClickOnce部署,则全部为您处理(至少在VS2008 SP1中); 只是:

  • 项目属性
  • 发布
  • 选项
  • 文件协会
  • (添加任何你需要的)

(注意,它必须是完全信任的,目标.NET 3.5,并且被设置为脱机使用)

另请参阅MSDN: 如何为ClickOnce应用程序创建文件关联

为什么选择不使用安装包来安装项目可能有一些特定的原因,但安装包是轻松执行应用程序配置任务的好地方,例如注册文件扩展名,添加桌面快捷方式等。

以下是如何使用内置的Visual Studio安装工具创建文件扩展名关联:

  1. 在现有的C#解决方案中,添加一个新项目并选择项目类型作为Other Project Types – > Setup and Deployment – > Setup Project (或者尝试安装向导)

  2. 配置你的安装程序(如果你需要帮助,大量现有的文档)

  3. 右键单击解决方案资源管理器中的安装项目,选择“ View – >“ File Types ,然后添加要与程序一起注册的扩展以运行它。

如果用户为您的应用程序运行卸载,则此方法还具有清理其他功能的好处。

这是一个完整的例子:

 public class FileAssociation { public string Extension { get; set; } public string ProgId { get; set; } public string FileTypeDescription { get; set; } public string ExecutableFilePath { get; set; } } public class FileAssociations { // needed so that Explorer windows get refreshed after the registry is updated [System.Runtime.InteropServices.DllImport("Shell32.dll")] private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); private const int SHCNE_ASSOCCHANGED = 0x8000000; private const int SHCNF_FLUSH = 0x1000; public static void EnsureAssociationsSet() { var filePath = Process.GetCurrentProcess().MainModule.FileName; EnsureAssociationsSet( new FileAssociation { Extension = ".binlog", ProgId = "MSBuildBinaryLog", FileTypeDescription = "MSBuild Binary Log", ExecutableFilePath = filePath }, new FileAssociation { Extension = ".buildlog", ProgId = "MSBuildStructuredLog", FileTypeDescription = "MSBuild Structured Log", ExecutableFilePath = filePath }); } public static void EnsureAssociationsSet(params FileAssociation[] associations) { bool madeChanges = false; foreach (var association in associations) { madeChanges |= SetAssociation( association.Extension, association.ProgId, association.FileTypeDescription, association.ExecutableFilePath); } if (madeChanges) { SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero); } } public static bool SetAssociation(string extension, string progId, string fileTypeDescription, string applicationFilePath) { bool madeChanges = false; madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + extension, progId); madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + progId, fileTypeDescription); madeChanges |= SetKeyDefaultValue($@"Software\Classes\{progId}\shell\open\command", "\"" + applicationFilePath + "\" \"%1\""); return madeChanges; } private static bool SetKeyDefaultValue(string keyPath, string value) { using (var key = Registry.CurrentUser.CreateSubKey(keyPath)) { if (key.GetValue(null) as string != value) { key.SetValue(null, value); return true; } } return false; } 

具体关于“Windows注册表”的方式:

我在HKEY_CURRENT_USER \ Software \ Classes下创建密钥(就像Ishmaeel所说的)

并按照X-Cubed回答的指示。

示例代码如下所示:

 private void Create_abc_FileAssociation() { /***********************************/ /**** Key1: Create ".abc" entry ****/ /***********************************/ Microsoft.Win32.RegistryKey key1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true); key1.CreateSubKey("Classes"); key1 = key1.OpenSubKey("Classes", true); key1.CreateSubKey(".abc"); key1 = key1.OpenSubKey(".abc", true); key1.SetValue("", "DemoKeyValue"); // Set default key value key1.Close(); /*******************************************************/ /**** Key2: Create "DemoKeyValue\DefaultIcon" entry ****/ /*******************************************************/ Microsoft.Win32.RegistryKey key2 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true); key2.CreateSubKey("Classes"); key2 = key2.OpenSubKey("Classes", true); key2.CreateSubKey("DemoKeyValue"); key2 = key2.OpenSubKey("DemoKeyValue", true); key2.CreateSubKey("DefaultIcon"); key2 = key2.OpenSubKey("DefaultIcon", true); key2.SetValue("", "\"" + "(The icon path you desire)" + "\""); // Set default key value key2.Close(); /**************************************************************/ /**** Key3: Create "DemoKeyValue\shell\open\command" entry ****/ /**************************************************************/ Microsoft.Win32.RegistryKey key3 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true); key3.CreateSubKey("Classes"); key3 = key3.OpenSubKey("Classes", true); key3.CreateSubKey("DemoKeyValue"); key3 = key3.OpenSubKey("DemoKeyValue", true); key3.CreateSubKey("shell"); key3 = key3.OpenSubKey("shell", true); key3.CreateSubKey("open"); key3 = key3.OpenSubKey("open", true); key3.CreateSubKey("command"); key3 = key3.OpenSubKey("command", true); key3.SetValue("", "\"" + "(The application path you desire)" + "\"" + " \"%1\""); // Set default key value key3.Close(); } 

只是告诉你们一个快速演示,很容易理解。 你可以修改这些关键值,一切都很好。

文件关联在HKEY_CLASSES_ROOT下的注册表中定义。

这里有一个VB.NET的例子,我可以很容易地移植到C#。

从Windows 7开始,有两个cmd工具可以轻松创建简单的文件关联。 他们是联合和ftype 。 这是每个命令的基本解释。

  • Assoc – 将文件扩展名(如“.txt”)与“文件类型”相关联。
  • FType – 定义一个可执行文件,当用户打开一个给定的“文件类型”时运行。

请注意,这些是cmd工具而不是可执行文件(exe)。 这意味着它们只能在cmd窗口中运行,或者使用ShellExecute和“cmd / c assoc”运行。 您可以通过链接了解更多关于它们的信息,或者通过键入“assoc /?” 和“ftype /?” 在cmd提示符下。

因此,要将应用程序与.bob扩展名相关联,可以打开一个cmd窗口(WindowKey + R,输入cmd,按回车键)并运行以下命令:

 assoc .bob=BobFile ftype BobFile=c:\temp\BobView.exe "%1" 

这比混淆注册表要简单得多,而且更有可能在未来的Windows版本中工作。

把它包起来,这是一个C#函数来创建一个文件关联:

 public static int setFileAssociation(string[] extensions, string fileType, string openCommandString) { int v = execute("cmd", "/c ftype " + fileType + "=" + openCommandString); foreach (string ext in extensions) { v = execute("cmd", "/c assoc " + ext + "=" + fileType); if (v != 0) return v; } return v; } public static int execute(string exeFilename, string arguments) { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.CreateNoWindow = false; startInfo.UseShellExecute = true; startInfo.FileName = exeFilename; startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.Arguments = arguments; try { using (Process exeProcess = Process.Start(startInfo)) { exeProcess.WaitForExit(); return exeProcess.ExitCode; } } catch { return 1; } } 

下面的代码是一个函数应该工作,它在Windows注册表中添加所需的值。 通常我在我的可执行文件中运行SelfCreateAssociation(“。abc”)。 (表单构造函数或onload或onshown)每次执行可执行文件时,它都会更新当前用户的注册表项。 (如果你有一些改变,很好的调试)。 如果您需要有关注册表项的详细信息,请查看此MSDN链接。

https://msdn.microsoft.com/en-us/library/windows/desktop/dd758090(v=vs.85).aspx

获取有关常规ClassesRoot注册表项的更多信息。 看到这个MSDN文章。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724475(v=vs.85).aspx

 public enum KeyHiveSmall { ClassesRoot, CurrentUser, LocalMachine, } /// <summary> /// Create an associaten for a file extension in the windows registry /// CreateAssociation(@"vendor.application",".tmf","Tool file",@"C:\Windows\SYSWOW64\notepad.exe",@"%SystemRoot%\SYSWOW64\notepad.exe,0"); /// </summary> /// <param name="ProgID">eg vendor.application</param> /// <param name="extension">eg .tmf</param> /// <param name="description">eg Tool file</param> /// <param name="application">eg @"C:\Windows\SYSWOW64\notepad.exe"</param> /// <param name="icon">@"%SystemRoot%\SYSWOW64\notepad.exe,0"</param> /// <param name="hive">eg The user-specific settings have priority over the computer settings. KeyHive.LocalMachine need admin rights</param> public static void CreateAssociation(string ProgID, string extension, string description, string application, string icon, KeyHiveSmall hive = KeyHiveSmall.CurrentUser) { RegistryKey selectedKey = null; switch (hive) { case KeyHiveSmall.ClassesRoot: Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(extension).SetValue("", ProgID); selectedKey = Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(ProgID); break; case KeyHiveSmall.CurrentUser: Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + extension).SetValue("", ProgID); selectedKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + ProgID); break; case KeyHiveSmall.LocalMachine: Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"Software\Classes\" + extension).SetValue("", ProgID); selectedKey = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"Software\Classes\" + ProgID); break; } if (selectedKey != null) { if (description != null) { selectedKey.SetValue("", description); } if (icon != null) { selectedKey.CreateSubKey("DefaultIcon").SetValue("", icon, RegistryValueKind.ExpandString); selectedKey.CreateSubKey(@"Shell\Open").SetValue("icon", icon, RegistryValueKind.ExpandString); } if (application != null) { selectedKey.CreateSubKey(@"Shell\Open\command").SetValue("", "\"" + application + "\"" + " \"%1\"", RegistryValueKind.ExpandString); } } selectedKey.Flush(); selectedKey.Close(); } /// <summary> /// Creates a association for current running executable /// </summary> /// <param name="extension">eg .tmf</param> /// <param name="hive">eg KeyHive.LocalMachine need admin rights</param> /// <param name="description">eg Tool file. Displayed in explorer</param> public static void SelfCreateAssociation(string extension, KeyHiveSmall hive = KeyHiveSmall.CurrentUser, string description = "") { string ProgID = System.Reflection.Assembly.GetExecutingAssembly().EntryPoint.DeclaringType.FullName; string FileLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; CreateAssociation(ProgID, extension, description, FileLocation, FileLocation + ",0", hive); }