C# Windows Shell与多个文件的集成
我正在制作一个使用Windows Shell集成的程序,我所做的注册表更改如下: 例如,对于.txt,我看到C# Windows Shell与多个文件的集成,c#,shell,windows-explorer,C#,Shell,Windows Explorer,我正在制作一个使用Windows Shell集成的程序,我所做的注册表更改如下: 例如,对于.txt,我看到HKEY\u CLASSES\u ROOT\.txt>(默认值)的值是txtfile。我向HKEY\U CLASSES\U ROOT\txtfile\shell添加键myprogram>(默认),其值为用myprogram打开。在myprogram中,我添加了命令>(默认),其值为*指向我的程序的路径*%1。现在,当我右键单击一个.txt文件时,有一个选项可以用我的程序打开它 但当我使用多
HKEY\u CLASSES\u ROOT\.txt>(默认值)
的值是txtfile
。我向HKEY\U CLASSES\U ROOT\txtfile\shell
添加键myprogram>(默认)
,其值为用myprogram打开。在myprogram
中,我添加了命令>(默认)
,其值为*指向我的程序的路径*%1
。现在,当我右键单击一个.txt文件时,有一个选项可以用我的程序打开它
但当我使用多个.txt文件时,Windows会多次打开我的程序,每次都以另一个文件作为参数。但是我想用所有的文件和参数一次性打开我的程序。是否有一个选项可以通过更改注册表中的内容来实现这一点
如果没有,我也找不到一种方法来制作一个可以多次打开并将所有程序合并为一个的程序,所以如果有人能帮助我,我也可以这样做。顺便说一句,我正在用C#编写这个程序。处理这个问题的标准方法是使用互斥锁,以确保程序只运行一个实例。然后,当shell尝试启动一个新实例来打开每个文件时,新实例只需将消息传递给已经运行的实例并让它打开文件。一个可能的选项是检查程序的另一个实例是否已经运行。如果是,则将文件路径传递给要打开的实例。对于程序间通信,您可以随意使用,例如:.NET远程处理、命名管道、DDE、自定义窗口消息等。这是默认设置。您已经告诉shell,当单击“使用MYPROGRAM打开”时,将为每个选定的文件调用应用程序%1
解决此问题的最简单方法是使应用程序成为单个实例,并在选择另一个文件时向已在运行的实例发送消息。这样,启动应用程序的一个实例以打开一个文件,它会收到打开其他每个文件的请求。这就是通常使用C实现的方式++
如果您看一下,也有使用DDE的建议。我不知道如何从C#中访问DDE,而且它的用途已被弃用。您必须使您的应用程序成为“单实例”。
像这样的事情应该可以做到:
(未经测试的代码,仅供参考)
有关更好的示例,请参阅CodeProject解决方案。DDE仅适用于GUI应用程序。NEt远程处理更好,因为它适用于控制台和gui应用程序。我只是按照文档中的说明提出建议。通常,我使用单个实例和每个文件的后续消息。我不倾向于使用DDE,因为它被列为“不推荐”已经很长时间了。您的代码没有真正起作用,但是CodeProject示例起作用了,谢谢。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace YourApp
{
class Program
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[STAThread]
static void Main()
{
bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 frm = new Form1();
frm.SetNewData("send command line here");
Application.Run(frm);
}
else
{
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
SetForegroundWindow(process.MainWindowHandle);
// send message to that form or use .Net remoting
break;
}
}
}
}
}
}
}