我有一个程序可以使用资源管理器中的右键菜单打开一个文件。但是,如果我选择多个文件,然后右键单击并使用我的程序打开,那么它会打开我的程序的多个实例,而不是仅仅将多个文件作为参数传递给单个实例。该程序是用 vb.net 编写的,但不是 windows 窗体,它只是一个模块,所以我可以在 Visual Studio 的属性中勾选 Single instance 选项。
那么如何在单个实例中从资源管理器上下文菜单中打开多个文件。
我有一个程序可以使用资源管理器中的右键菜单打开一个文件。但是,如果我选择多个文件,然后右键单击并使用我的程序打开,那么它会打开我的程序的多个实例,而不是仅仅将多个文件作为参数传递给单个实例。该程序是用 vb.net 编写的,但不是 windows 窗体,它只是一个模块,所以我可以在 Visual Studio 的属性中勾选 Single instance 选项。
那么如何在单个实例中从资源管理器上下文菜单中打开多个文件。
这里没有满意的答案,Windows 资源管理器没有提供一种简单的方法来启动程序并传递所有选定的文件。这需要一个shell 上下文菜单处理程序,它们很难用托管代码编写。直到 .NET 4.0 都无法安全地编写。
然而,使用 VB.NET 中可用的应用程序框架来模拟它很容易,使您的应用程序成为单例并实现StartupNextInstance 事件。唯一的问题是这不是特别快。而且它在控制台模式应用程序中不起作用。
此链接通过单击上下文菜单项帮助我在资源管理器中获取所选文件的路径: .NET Shell Extensions - Shell Context Menus
它是 C# 语言,但正如那篇文章海报所说,它也可以在 vb.net 中使用。
真的很容易:)
希望这对你也有帮助!:)
这是步骤:
1) 下载你的 SharpShell 库>>
下载文章顶部的“SharpShell 库”zip 文件,并添加对下载的 SharpShell.dll 文件的引用。
或者您可以通过 Nuget 下载它:
如果您安装了 Nuget,只需快速搜索 SharpShell 并直接安装它 - 或在https://www.nuget.org/packages/SharpShell获取包详细信息。
添加以下引用:
System.Windows.Forms
System.Drawing
在代码顶部使用这些:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpShell;
using SharpShell.SharpContextMenu;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using SharpShell.Attributes;
派生你的类从SharpContextMenu
右键单击该行的 SharpContextMenu 部分并选择Implement Abstract Class
。
可以显示菜单
调用此函数来确定我们是否应该显示给定文件集的上下文菜单扩展。用户选择的文件在属性中SelectedItemPaths
。我们可以检查这些文件路径,看看我们是否真的想要显示菜单。如果应该显示菜单,请返回true
。如果没有,返回false
。
创建菜单
调用此函数以实际创建上下文菜单。ContextMenuStrip
我们只需要返回一个标准的 WinForms 。
这是整个命名空间源代码:
namespace CountLinesExtension
{
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class Class1 : SharpContextMenu
{
protected override bool CanShowMenu()
{
// We will always show the menu.
return true;
//throw new NotImplementedException();
}
protected override ContextMenuStrip CreateMenu()
{
// Create the menu strip.
var menu = new ContextMenuStrip();
// Create a 'count lines' item.
var itemCountLines = new ToolStripMenuItem
{
Text = "Count Lines"
};
// When we click, we'll call the 'CountLines' function.
itemCountLines.Click += (sender, args) => CountLines();
// Add the item to the context menu.
menu.Items.Add(itemCountLines);
// Return the menu.
return menu;
//throw new NotImplementedException();
}
private void CountLines()
{
// Builder for the output.
var builder = new StringBuilder();
// Go through each file.
foreach (var filePath in SelectedItemPaths)
{
// Count the lines.
builder.AppendLine(string.Format("{0} - {1} Lines",
Path.GetFileName(filePath), File.ReadAllLines(filePath).Length));
}
// Show the ouput.
MessageBox.Show(builder.ToString());
}
}
}
接下来,我们必须给程序集起一个强名称。有一些方法可以绕过这个要求,但通常这是最好的方法。为此,请右键单击项目并选择“属性”。然后转到“签名”。选择“签署程序集”,为密钥指定“新建”并选择密钥名称。您可以根据需要对密钥进行密码保护,但这不是必需的
现在安装并注册 Shell 扩展:regasm 工具
您可以使用工具“regasm”来安装和注册一个 shell 扩展。使用 regasm 时,shell 扩展将安装到注册表中(即 COM 服务器的类 ID 将放在 COM 服务器类部分并与实际服务器文件的路径相关联),它还将注册关联。
服务器管理器工具
服务器管理器工具是我首选的安装/卸载和注册/注销方法,至少在开发期间是这样,因为它允许您将安装和注册作为单独的步骤。它还可以让您指定是在 32 位还是 64 位模式下安装/卸载等。
这是整个示例源代码。我们可以添加任意数量的上下文菜单项、任何功能、任何文件扩展等。
虽然我知道这是针对 vb.net 的,但我相信您只需进行一些修改即可使用此 c# 代码,这对我有用。也许这不是最好的方法,但对我来说,这是最简单的方法。在运行第二个副本之前,它会检查应用程序标题当前是否正在运行。
这是在 Program.cs
static frmMain Form;
[STAThread]
static void Main(string[] args)
{
bool blnCurrentlyRunning = false;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Process[] processes = Process.GetProcesses();
foreach (var item in processes)
{
if (item.MainWindowTitle.IndexOf("Application Title") != -1)
blnCurrentlyRunning = true;
}
if (!blnCurrentlyRunning)
{
Form = new frmMain();
Application.Run(Form);
}
else
{
Application.Exit();
}
}