如何实现双击打开多个文件时,调用同一个自编程序打开?

时间:2022-06-01 18:47:00
如题,设置自编程序为某类型文件默认关联程序,双击打开文件时,会启动一个新的程序。在程序启动时判断相同的程序进程已启动时,如何将要打开的文件名传递到这个已启动的进程?

4 个解决方案

#1


改写自:如何操作我的程序的另一个实例
http://blog.csdn.net/gomoku/article/details/4798331


// Program.cs
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            // 尝试创建一个命名事件
            bool createNew;
            ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, @"MyStartEvent", out createNew);

            // 如果该命名事件已经存在(存在有前一个运行实例),则
            if (!createNew)
            {
                // 先写一些数据到注册表中,以便传递给前一个运行实例
                SetDataToRegistry(args.FirstOrDefault() ?? "空白");

                // 发事件通知
                ProgramStarted.Set();

                // 将焦点转移到前一个实例
                foreach (Process p in Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName))
                {
                    if (p.MainWindowHandle != IntPtr.Zero)
                    {
                        SetForegroundWindow(p.MainWindowHandle);
                    }
                }

                // 就此退出第二个进程
                return;
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }

        internal static EventWaitHandle ProgramStarted;
        internal static void SetDataToRegistry(string data)
        {
            Registry.SetValue(@"HKEY_CURRENT_USER\Software\MyMy", "", data);
        }
        internal static string GetDataFromRegistry()
        {
            return Registry.GetValue(@"HKEY_CURRENT_USER\Software\MyMy", "", "") as string;
        }

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern bool SetForegroundWindow(IntPtr hWnd);
    }
}

#2



// Form1.cs
using System;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        ListBox listBox = new ListBox() { Dock = DockStyle.Fill};
        public Form1()
        {
            //InitializeComponent();
            this.Controls.Add(listBox);
            ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
        }

        // 当收到第二个进程的通知时,从注册表中获得传入的参数,并恢复窗口显示
        void OnProgramStarted(object state, bool timeout)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new WaitOrTimerCallback(OnProgramStarted), state, timeout);
            }
            else
            {
                listBox.Items.Add(Program.GetDataFromRegistry());
            }
        }
    }
}


#3


 string keyName;
string keyValue;
 
keyName = "MyApp";
keyValue = "My Application";
   
RegistryKey key;
key = Registry.ClassesRoot.CreateSubKey(keyName);
key.SetValue("", keyValue);
key = key.CreateSubKey("shell");
key = key.CreateSubKey("open");
key = key.CreateSubKey("command");
key.SetValue("", "C:\\myApp.exe %1");
 
keyName = ".bar"; //相应后缀
keyValue = "MyApp";
key = Registry.ClassesRoot.CreateSubKey(keyName);
key.SetValue("", keyValue);


程序入口
[STAThread]
static void Main(string[] args)
{
    if(args.Length > 0)
        Application.Run(new FrmMain(args[0])); //args[0] 就是双击打开的文件名(包含文件路径)
    else
        Application.Run(new FrmMain(null));
}

#4


进程间通讯方法太多了,简单参数用共享内存也行,像桌面应用这种,还可以向先打开的程序发送WM_COPYDATA消息
重写WndProc时捕获自处理一下就好(文件参数放在lPara中)

#1


改写自:如何操作我的程序的另一个实例
http://blog.csdn.net/gomoku/article/details/4798331


// Program.cs
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            // 尝试创建一个命名事件
            bool createNew;
            ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, @"MyStartEvent", out createNew);

            // 如果该命名事件已经存在(存在有前一个运行实例),则
            if (!createNew)
            {
                // 先写一些数据到注册表中,以便传递给前一个运行实例
                SetDataToRegistry(args.FirstOrDefault() ?? "空白");

                // 发事件通知
                ProgramStarted.Set();

                // 将焦点转移到前一个实例
                foreach (Process p in Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName))
                {
                    if (p.MainWindowHandle != IntPtr.Zero)
                    {
                        SetForegroundWindow(p.MainWindowHandle);
                    }
                }

                // 就此退出第二个进程
                return;
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }

        internal static EventWaitHandle ProgramStarted;
        internal static void SetDataToRegistry(string data)
        {
            Registry.SetValue(@"HKEY_CURRENT_USER\Software\MyMy", "", data);
        }
        internal static string GetDataFromRegistry()
        {
            return Registry.GetValue(@"HKEY_CURRENT_USER\Software\MyMy", "", "") as string;
        }

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern bool SetForegroundWindow(IntPtr hWnd);
    }
}

#2



// Form1.cs
using System;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        ListBox listBox = new ListBox() { Dock = DockStyle.Fill};
        public Form1()
        {
            //InitializeComponent();
            this.Controls.Add(listBox);
            ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
        }

        // 当收到第二个进程的通知时,从注册表中获得传入的参数,并恢复窗口显示
        void OnProgramStarted(object state, bool timeout)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new WaitOrTimerCallback(OnProgramStarted), state, timeout);
            }
            else
            {
                listBox.Items.Add(Program.GetDataFromRegistry());
            }
        }
    }
}


#3


 string keyName;
string keyValue;
 
keyName = "MyApp";
keyValue = "My Application";
   
RegistryKey key;
key = Registry.ClassesRoot.CreateSubKey(keyName);
key.SetValue("", keyValue);
key = key.CreateSubKey("shell");
key = key.CreateSubKey("open");
key = key.CreateSubKey("command");
key.SetValue("", "C:\\myApp.exe %1");
 
keyName = ".bar"; //相应后缀
keyValue = "MyApp";
key = Registry.ClassesRoot.CreateSubKey(keyName);
key.SetValue("", keyValue);


程序入口
[STAThread]
static void Main(string[] args)
{
    if(args.Length > 0)
        Application.Run(new FrmMain(args[0])); //args[0] 就是双击打开的文件名(包含文件路径)
    else
        Application.Run(new FrmMain(null));
}

#4


进程间通讯方法太多了,简单参数用共享内存也行,像桌面应用这种,还可以向先打开的程序发送WM_COPYDATA消息
重写WndProc时捕获自处理一下就好(文件参数放在lPara中)