Windows Shell Integration with multiple files
I'm making a prog开发者_运维知识库ram that is using Windows Shell Integration, and the registry changes I do are these:
For example, for .txt, I see that the value for HKEY_CLASSES_ROOT\.txt > (Default)
is txtfile
. I add to HKEY_CLASSES_ROOT\txtfile\shell
the key myprogram > (Default)
with the value Open with MYPROGRAM
. to myprogram
I add command > (Default)
with the value *path-to-my-program* %1
. Now when I right click a .txt file there is an option to open it with my program.
But when I do that with multiple .txt files Windows opens my program many times with each time another file as argument. But I want to open my program one time with all the files as many arguments. Is there an option to do that with changing stuff in registry?
If not, I also could not find a way to make a program that can be opened multiple times and combine all of them to one, so I can also do it that way if someone can help me with it. I'm making this program with C#, by the way.
You have to make your application "Single Instance". Something like this should do the trick: (untested code, just for reference)
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;
}
}
}
}
}
}
}
For a better example see this CodeProject solution.
The standard way to handle this is to use a mutex to ensure that only a single instance of your program runs. Then when the shell attempts to start up a new instance to open each file, the new instance simply passes the message on to the already running instance and lets it open the file.
One possible option is to check if another instance of your program is already running. If so, you pass the file path to that instance to open. For program inter-communication you can use whatever you like, e.g.: .NET remoting, named pipes, DDE, custom window messages, etc..
That's the default. you have told the shell that when clicking 'open with MYPROGRAM' invoke application %1 for each file that is selected.
The simplest way to fix this is to make your application single instance, and to send messages to the instance that is already running when another file is selected. This way one instance of your application is launched to open one file and it receives a request to open each of the other files. This is how it is generally accomplished using C++
if you look at the Developer Documentation there is also the recommendation to use DDE. I don't know how accessible DDE is from within C#, and it's use is deprecated.
精彩评论