【问题标题】:Windows Shell Integration with multiple files与多个文件的 Windows Shell 集成
【发布时间】:2011-06-29 21:40:27
【问题描述】:

我正在制作一个使用 Windows Shell 集成的程序,我所做的注册表更改如下: 例如,对于 .txt,我看到 HKEY_CLASSES_ROOT\.txt > (Default) 的值是 txtfile。我将值Open with MYPROGRAM 添加到HKEY_CLASSES_ROOT\txtfile\shellmyprogram > (Default)。到myprogram 我添加command > (Default) 和值*path-to-my-program* %1。现在,当我右键单击一个 .txt 文件时,有一个选项可以用我的程序打开它。

但是当我对多个 .txt 文件执行此操作时,Windows 会多次打开我的程序,每次都将另一个文件作为参数。但是我想一次打开我的程序,所有文件的参数都一样多。是否可以通过更改注册表中的内容来做到这一点?

如果没有,我也找不到一种方法来制作一个可以多次打开的程序并将它们全部合并为一个,所以如果有人可以帮助我,我也可以这样做。顺便说一句,我正在用 C# 编写这个程序。

【问题讨论】:

    标签: c# shell windows-explorer


    【解决方案1】:

    您必须使您的应用程序“单实例”。 这样的事情应该可以解决问题: (未经测试的代码,仅供参考)

    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;
                            }
                        }
                    }
                }
            }
        }
    }
    

    有关更好的示例,请参阅this CodeProject 解决方案。

    【讨论】:

    • 您的代码并没有真正工作,但 CodeProject 示例可以,谢谢。
    【解决方案2】:

    处理这个问题的标准方法是使用互斥锁来确保只有一个程序实例运行。然后当 shell 尝试启动一个新实例来打开每个文件时,新实例只是将消息传递给已经运行的实例并让它打开文件。

    【讨论】:

      【解决方案3】:

      一个可能的选择是检查您的程序的另一个实例是否已经在运行。如果是这样,则将文件路径传递给该实例以打开。对于程序间通信,您可以使用任何您喜欢的方式,例如:.NET 远程处理、命名管道、DDE、自定义窗口消息等。

      【讨论】:

        【解决方案4】:

        这是默认设置。您已经告诉 shell,当单击“使用 MYPROGRAM 打开”时,为每个选定的文件调用 应用程序 %1。

        解决此问题的最简单方法是使您的应用程序成为单一实例,并在选择另一个文件时向已运行的实例发送消息。这样,您的应用程序的一个实例会启动以打开一个文件,并且它会收到打开其他每个文件的请求。这就是通常使用 C++ 完成的方式

        如果您查看Developer Documentation,还有使用 DDE 的建议。我不知道 DDE 在 C# 中的可访问性,它的使用已被弃用。

        【讨论】:

        • DDE 仅适用于 GUI 应用程序。 IE。 .NEt 远程处理更好,因为它适用于控制台和 gui 应用程序。
        • 我只是按照文档中的说明提出建议。通常,我使用单个实例和每个文件的后续消息。我不倾向于使用 DDE,因为它被列为“不推荐”很长时间了。
        猜你喜欢
        • 1970-01-01
        • 2013-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-15
        • 2011-10-08
        相关资源
        最近更新 更多