如何在 C++ 中编写 shell 扩展?
Posted
技术标签:
【中文标题】如何在 C++ 中编写 shell 扩展?【英文标题】:How to write a shell extension in C++? 【发布时间】:2012-02-07 08:34:35 【问题描述】:这似乎是一个常见问题,但在进行了一些搜索后,我并没有真正找到答案。这里有一篇文章:
http://www.codeproject.com/KB/shell/shellextguide1.aspx
但它适用于非常旧的 Visual Studio 版本。我使用的是 VS 2008,所以说明和界面似乎与我看到的不符。
我想使用 C++ 创建一个简单的 shell 扩展,为扩展名为 .GZ 的文件创建上下文菜单。右键单击这些文件时,我应该能够单击上下文菜单项并在代码中进行回调以对该文件执行某种操作。
其他上下文菜单项会执行一些操作,例如生成无模式对话框以在执行某些操作之前接受用户输入。
据我所见,ATL 用于此目的,但我从未使用过 ATL,因此所有对象类型和接口都让我感到非常困惑。如果我有合适的教程或文档可供阅读,那就不会那么糟糕了。
谁能帮帮我?是不是有某种未满 10 年的教程?
【问题讨论】:
这其实是一件特别难做的事情。当用户右键单击打印机时,我开发了一个上下文菜单项。尽管我的代码只有 40 行左右,但生成的代码大约有 1,000 行。我希望我能更有帮助,但我不能分享我拥有的任何代码。作为提示,您的 shell 扩展必须驻留在 DLL 中,并且它必须有自己的 GUID,并且 DLL 需要使用 regsvr32 注册。您想要实现BOTH IContextMenu 和IShellExtInit COM 接口。有一种方法可以让 VS 为您生成大部分内容,但我不记得如何了。 IContextMenu doc,还有IShellExtInit doc。 @dreamlax 我在 ATL 项目中使用了项目向导,但是当我创建一个新类时,它也会为它创建一个接口——我不想要一个接口,但它看起来并不容易删除该功能。另外我不确定为什么需要生成代码。 我不记得具体的ATL实现细节了;我已经很久没有使用 ATL 或 C++ 了。 :) 不过,我记得所涉及的头痛。您可能会发现 this link 很有帮助;它专门用于 VS 2010 C++,并演示了上下文菜单扩展。这是ATL example for VS 2008 C++ 10 年前的教程很好。那段时间什么都没有改变。无论如何,您甚至不需要外壳扩展。您可以将项目添加到生成可执行文件的上下文菜单中,并将文件名作为参数传递。您只需使用注册表设置即可。轻松上手的最简单方法。 【参考方案1】:我不能确切地告诉你如何编写一个 shell 扩展,但我会提供一些提示。与简单得多的“仅注册”方法相比,编写 Shell 扩展具有一些显着优势:
使用 Shell 扩展,您可以动态创建与所选文件更相关的上下文菜单项(或子菜单)。例如,如果您正在为 zip 文件编写 Shell 扩展,则可以在上下文菜单中创建一个子菜单来显示 zip 的全部内容。 您可以同时处理多个文件,这不仅有利于提高性能,而且还可以根据整个选择而不是仅针对每个文件来确定要执行的操作。Shell 扩展的一些缺点是:
大大增加了复杂性。准备好为此付出很多努力以使其正常工作。在您的计算机旁边安装一台家用浓缩咖啡机和/或雇人为您煮咖啡。
大大增加了调试的难度。咖啡也是如此。
很难编写 Shell 扩展,因为它们很难调试。
Shell 扩展由explorer.exe
进程加载,如果没有特定的资源管理器配置,您需要强制退出explorer.exe
进程,以便安装更新版本的Shell 扩展。有一种方法可以让 Explorer 卸载它不再使用的 DLL,但您应该只在开发机器上而不是在部署目标上执行此操作:
在 RegEdit 中,浏览到以下键:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
添加一个名为“AlwaysUnloadDLL”的新 DWORD 键并将其值设置为 1。
重启资源管理器。
这在大多数情况下都有效,但有时您可能仍需要关闭资源管理器,因为未卸载 Shell 扩展。
请记住,您的 Shell 扩展可能会被其他应用程序加载,例如,如果您右键单击带有应用程序“打开文件”对话框的文件,那么您的 Shell 扩展将被加载到该应用程序中,而不是探险家。
如果您的 Shell 扩展导致运行时错误,结果通常只是您的上下文菜单项未显示,很少会告诉您您的 Shell 扩展未能加载或导致运行时错误。
配置可能很困难,即使在安装时,也需要在多个位置创建注册表数据,并且根据您希望上下文菜单显示的位置,注册表中的位置可能会因 Windows 的不同版本而有所不同。
你需要做什么:
Visual Studio 提供了一些创建 Shell 扩展的快捷方式,但基本上您需要创建一个 COM DLL。上下文菜单项的 Shell 扩展必须实现IContextMenu
接口和IShellExtInit
接口。
在IShellExtInit::Initialize()
方法中,可以通过IDataObject
参数获取选中的文件。从内存中,数据采用“Drag-n-Drop”格式,因此您需要从IDataObject
获取HDROP
句柄并从那里查询文件(这是来自内存,实际上可能与我在此处进行了描述,因此请谨慎操作)。
准备好“安装”您的 DLL 后,您必须将其复制到某处,然后运行 regsvr32
以确保它已注册。
关注this guide,了解将注册表项放在何处。
可能在 64 位 Windows 上存在问题,如果您构建 32 位 DLL,它可能无法在 64 位资源管理器中加载……因此,如果您在 64 位上遇到问题,请记住这一点位窗口。
您的 DLL 实际上会有 两个 与之关联的 GUID。我不记得它是如何工作的,但一个 GUID 指的是 DLL 本身,另一个指的是实际的 Shell 扩展。在需要 GUID 的注册表中创建密钥时,请确保使用实际 Shell 扩展的 GUID。
所有事情都考虑...(tl;dr)
权衡外壳扩展是否值得的成本。如果您想根据所选文件动态创建菜单项,那么外壳扩展可能是唯一的方法。如果您想同时处理所有文件,那么您可能还需要一个 Shell 扩展。
上下文菜单方法的替代方法是在用户桌面上放置一个拖放目标或其他东西。探索可以让用户将文件提交到应用程序的其他方法,因为 Shell 扩展通常付出的努力远远超过它的价值。我很难找到这一点,我想其他人也一样。
【讨论】:
+1 很棒的帖子,.NET 4 让事情变得更容易了,您现在可以在托管代码中编写 shell 扩展。在这里提及它,以免人们完全被劝阻。 @blak3r 那seems 气馁。以上是关于如何在 C++ 中编写 shell 扩展?的主要内容,如果未能解决你的问题,请参考以下文章