我自己的前言说明:
本文原作者为 Dave Kerr ,原文链接为 .NET Shell Extensions - Shell Context Menus ,我是在为了完成最新需求的时候查询资料的时候发现的,因为太久没有看外文资料了,所以为了锻炼一下翻译的,文中有一句未能翻译出来.
Download SharpShell source code - 1.8 MB
Download SharpShell Tools - 181.1 KB
Download SharpShell core library - 90.9 KB
引言:
一直到. NET 4.0 为止,我们都还是不能通过. NET 代码完全实现外壳扩展的功能.但是随着 framework 的不断提高,现在我们已经可以实现这个功能了.在本文中,我将带领你通过 C# 类文件快速实现右键菜单扩展功能.
(图中是已经实现的功能,"Count Lines" 是我自定义的一个右键选项,文章将仔细解释如何实现该功能)
".NET 外壳扩展" 索引:
本文只是 ".NET 外壳扩展" 的一部分,本系列还包括:
.NET Shell Extensions - Shell Context Menus
.NET Shell Extensions - Shell Icon Handlers
.NET Shell Extensions - Shell Info Tip Handlers
.NET Shell Extensions - Shell Drop Handlers
.NET Shell Extensions - Shell Preview Handlers
.NET Shell Extensions - Shell Icon Overlay Handlers
.NET Shell Extensions - Shell Thumbnail Handlers
.NET Shell Extensions - Shell Property Sheets
.NET Shell Extensions - Deploying SharpShell Servers
什么是 Shell Context Menus?
Shell Context Menus 是在系统中注册,允许扩展 shell 对象的 Context 菜单的 COM 服务器.这里说的对象可以明确到具体的文件类型,例如 ".txt" 文件,驱动,文件或者其他的文件类型.这时的 Context 菜单可以通过 Windows 管理器快速访问到更多的信息.
准备:
实现外壳扩展功能有很多工作需要完成:我们需要实现具体的 COM 接口,需要提供服务,并通过各种方式更新注册表.现在我们可以调用我已经写好的一个叫做 "SharpShell" 库来完成这些复杂的功能,这样我们的任务就变成了只需要创建一个包含已完成延展功能类的轻量级的类库了.
我们的目标:
下面所示代码创建了一个 shell 扩展,允许你通过右键并选择 "Count Lines" 来计算出任何文本文件中的行数.另外在文章后半部分我将详细讲解如何创建下面所示的库.我先将代码显示出来的意图是为了强调在调用 SharpShell 库的情况下如何直截了当的完成库的书写
/// <summary>
/// The CountLinesExtensions is an example shell context menu extension,
/// implemented with SharpShell. It adds the command 'Count Lines' to text
/// files.
/// </summary>
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class CountLinesExtension : SharpContextMenu
{
/// <summary>
/// Determines whether this instance can a shell
/// context show menu, given the specified selected file list.
/// </summary>
/// <returns>
/// <c>true</c> if this instance should show a shell context
/// menu for the specified file list; otherwise, <c>false</c>.
/// </returns>
protected override bool CanShowMenu()
{
// We always show the menu.
return true;
}
/// <summary>
/// Creates the context menu. This can be a single menu item or a tree of them.
/// </summary>
/// <returns>
/// The context menu for the shell context menu.
/// </returns>
protected override ContextMenuStrip CreateMenu()
{
// Create the menu strip.
var menu = new ContextMenuStrip();
// Create a 'count lines' item.
var itemCountLines = new ToolStripMenuItem
{
Text = "Count Lines...",
Image = Properties.Resources.CountLines
};
// When we click, we'll count the lines.
itemCountLines.Click += (sender, args) => CountLines();
// Add the item to the context menu.
menu.Items.Add(itemCountLines);
// Return the menu.
return menu;
}
/// <summary>
/// Counts the lines in the selected files.
/// </summary>
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());
}
}
代码可以说简单清晰了,现在就让我们开始仔细研究具体的实现过程吧.
第一步:新建项目
首先,我们需要开始一个新的 C# 类库项目.
提示:你也可以除了 C#,还可以使用 VB,在本文中虽然所有的代码都是 C#,但是方法原理均同理可得.
在本例中,我们的项目名称是 "CountLinesExtension".
现在我们需要添加一下的引用:
System.Windows.Forms
System.Drawing
之所以需要
System.Windows.Forms
,是因为我们需要通过 WinForms ContextMenuStrip 来定义 context 菜单.而需要调用 System.Drawing 的原因在于我们想要用到 Icons.
将'Class1.cs'重命名为'CountLinesExtension.cs'. 那么目前我们项目的就变成了这样了:
第二步:引用 SharpShell
现在我们需要添加对 SharpShell 的引用.你可以通过以下这些不同的方法:
添加引用:
在文章最开始的地方下载'SharpShell Library'压缩文件,然后直接对 SharpShell.dll 文件添加引用即可.
提示:文章开始的下载文件是在此文写的时候的文件,如果你想要获得最新的版本,请通过 Nuget 或者从 sharpshell.codeplex.com 获取.
Nuget
如果你电脑有 Nuget,那么就只需要简单检索 SharpShell 并安装即可,或者直接访问: https://www.nuget.org/packages/SharpShell
CodePlex
从 CodePlex 的里面专门的 SharpShell 主页 sharpshell.codeplex.com 中你直接可以得到最新的版本.Nuget 上虽然也有最新的可靠的版本,但是 CodePlex 可以还有可用的已写好的 betas,而且那上面的文章里面的版本基本都是可用的.
第三步:SharpContextMenu
现在开始就开始真正的研究了,注意了哦.我们的 CountLinesExtension 继承于 SharpContextMenu:
/// <summary>
/// The Count Lines Context Menu Extension
/// </summary>
public class CountLinesExtension : SharpContextMenu
{
}
现在我们既然继承于 SharpContextMenu 这个父类,那我们就要来实现这个抽象类.右键选择 SharpContextMenu,然后选择'Implement Abstract Class':
这个操作将会自动生成 SharpContextMenu 的两个函数 - CanShowMenu 和 CreateMenu:
/// <summary>
/// The Count Lines Context Menu Extension
/// </summary>
public class CountLinesExtension : SharpContextMenu
{
protected override bool CanShowMenu()
{
throw new NotImplementedException();
}
protected override ContextMenuStrip CreateMenu()
{
throw new NotImplementedException();
}
}
通过实现这两个函数没我们可以实现我们所需的所有功能.两个函数功能具体介绍:
CanShowMenu (好像有点不对)
这个函数来决定当前的文件是否是我们需要用来显示扩展菜单的文件.被选中的文件类型是 SelectedItemPaths 的属性.我们可以通过检查来判断当前的文件类型是不是符合要求的文件类型.如果需要显示菜单就返回 true,否则就返回 false.
CreateMenu
这个函数实现主要的功能.我们需要返回 WinForms 的 ContextMenuStrip.
下面是具体的实现:
protected override bool CanShowMenu()
{
// We will always show the menu.
return true;
}
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;
}
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());
}
对于 CanShowMenu,我们常常直接返回 true(很快我们就会明白为什么我们不需要验证我们的文本文件了).对于 CreateMenu,我们建立了一个显示菜单,里面只有一个选项,也就是'Count Lines',并实现读出行数的功能.
CountLines 这个功能的实现是通过 SelectedItemPaths 和读取每个文件的函数,然后总结好了显示在弹窗里.
第四步:处理 COM 注册
现在所剩的事情不多了.首先我们需要添加 COMVisible 的引用到我们的类里面.
[ComVisible(true)]
public class CountLinesExtension : SharpContextMenu
为什么呢?因为我们的类虽然看起来不像,但是他本质上也是一个 COM Server. 如果你了解一些基类,那么你可以看我们刚刚实现的 COM 接口,例如 IShellExtInit, IContextMenu, 和 ISharpShellServer.我们不用了解这里到底做了什么,凡是为了保证系统能够创建我们的扩展,她就必须有这个属性.
接下来,我们需要给程序集一个强名称.这里有很多方法实现这个要求,但是总体来说,这是最好的方法.现在我们单机程序右键,然后选择 "属性".再选择 "签名".选中 "为程序集签名",再选择 "选择强名称秘钥文件" 里面的 "新建",并输入新建的密钥文件名称.你可以自行选择是否需要使用密码保护密钥文件:
最后一步,我们需要关联我们的扩展到具体的文件类型了.这个的实现可以通过对
COMServerAssociation
(来源于 SharpShell)的引用:
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class CountLinesExtension : SharpContextMenu
在这里我们做了什么呢?我们告诉了 SharpShell,注册服务器时,我们想要关联任何与 ".txt" 相关的类.这就意味着我们不止是仅限于以. TXT 结尾的文件,而是任何同类的文件.更权威的说法是,大多是与 txt 文件共享同样图标的东西.
你可以用
COMServerAssociation
的属性来实现更多的功能,例如你还可以与文件夹,驱动,位置的文件来实现特定的扩展,等等.另外,关于 COM Server Associations 的详细的文献资料在 SharpShell CodePlex 上面.
好了,但目前为止就搞定了!我们已经创建一个可以在作为 COM server 在系统中添加自定义菜单的 CountLinesExtension 程序集项目了.关于注册 COM Server 和调试部署的任务,我们我们将在下一节,仔细讨论.
调试 Shell 扩展
这个 Shell 扩展功能将被加载到电脑资源管理器时,由于加载. NET COM Server 时各种迂回的方式,所以可以说让调试器进入进程并但不执行托管代码几乎可以说是不可能实现的事情.当然,这里还是有一个方法可以快速实现调试.Sharp Shell 有一些工具,让实现 COM Server 变得简单了,其中一个叫做:Server Manager.我们可以用这个工作实现调试.
打开 Server Manager 工具,然后点击 File,选择 Load Server,再加载已生成的文件(DLL 文件).你也可以直接拖动文件到主界面中.然后被选中的文件的详细信息就会在旁边显示了.
这个 Server Manager 非常好用,它可以告诉你服务是否已经安装了和其他各种信息.
如果你要加载 SharpContextMenu 服务,那就选中'Tools',然后你选中再选中'Test Context Menu'.
当你用到了'Test Context Menu'的时候,你会得到一份测试窗口.只是 Windows 资源管理器应用程序的基本实现.你可以通过右键单击来测试.
提示:不管你的 COMServerAssocations 已经生成了,测试的窗口都会不断的重新创建.
将调试器附加到 servermanager 过程将允许你调试你的上下文菜单和测试它的功能,而无需在 Windows 登记服务器.下面是运行 Count Line 上下文扩展菜单时测试 shell 的样子
安装和注册 Shell 扩展
这里又很多方法实现安装和注册 Shell 扩展.在接下来的这一节里我将仔细介绍这些.
regasm
你可以通过 regasm 这个工具来实现安装和祖册 shell 扩展.当使用 regasm 的时候 shell 会被装进注册表中(COM 服务器的类 ID 将放在 COM 服务器类部分,并与实际服务器文件的路径相关联),也会创建关联.
Server Manager
在开发过程中,服务器管理工具是我首选的安装 / 卸载和注册 / 注销的方法,因为它可以让安装和注册作为单独的步骤处理.它也将让你指定你是安装 / 卸载在 32 位还是 64 位模式中.
手动注册表操作
Generally a bad approach, but if you absolutely have to then the MSDN documentation for Shell Extensions describes the changes that must be made to the registry to manually register a COM server, or a Managed COM Server(这句不会翻译).这个文献资料被放在了下一节.
有用的资料
在 windows 中创建快捷菜单处理程序 :这是最重要的资料:关于 shell 菜单扩展如何在 windows 里具体运行的细节介绍.
CodePlex 上的 SharpShell :关于 SharpShell 项目的专门的主页:其中包罗了各种文献资料,大家的讨论,以及最新的代码研究资源和最新的版本.
后记
会逐渐通过 SharpShell 和. NET 的使用来时间实现更多的 shell 扩展功能,形成一个完整的系列.目前那我正在实现图标处理程序(正在编写文档),关于属性表处理程序问题已经实现了(还有些 bug 正在解决).
来源: https://www.cnblogs.com/Aries-rong/p/8320531.html