如何用C++编写shell扩展
How to write a shell extension in C++?
这似乎是一个常见的问题,但经过一些搜索,我真的找不到答案。这里有一篇关于这方面的文章:
http://www.codeproject.com/KB/shell/shellextguide1.aspx
但它是为一个非常旧的Visual Studio版本设计的。我使用的是VS2008,所以指令和接口似乎与我看到的不匹配。
我想用C++创建一个简单的shell扩展,为扩展名为.GZ的文件创建一个上下文菜单。当右键单击这些文件时,我应该能够单击上下文菜单项,并在代码中有一个回调来对该文件进行某种操作。
其他上下文菜单项会做一些事情,比如生成无模块对话框,以便在执行某些操作之前接受用户输入。
据我所见,ATL是用来做这件事的,但我从未使用过ATL,所以所有的对象类型和接口都让我很困惑。如果我有合适的教程或文档可以阅读,那也不会那么糟糕。
有人能帮我吗?难道没有一种不是10年前的教程吗?
我不能确切地告诉您如何编写shell扩展,但我将提供一些技巧。与更简单的"仅注册表"方法相比,编写Shell扩展提供了一些显著的优势:
- 使用Shell Extension,可以动态创建与选定文件更相关的上下文菜单项(或子菜单)。例如,如果您正在为zip文件编写Shell Extension,则可以在上下文菜单中创建一个子菜单,显示zip的全部内容
- 您可以同时处理多个文件,这不仅对性能更有利,而且可以根据整个选择而不仅仅是针对每个文件来确定要做什么
Shell Extensions的一些缺点是:
-
大大增加了复杂性。准备在这方面花费大量的精力来让它发挥作用。在你的电脑旁边安装一台家用意式浓缩咖啡机和/或雇个人为你煮咖啡。
-
大大增加了调试难度。咖啡也是如此。
编写Shell扩展很困难,因为它们很难调试。
-
Shell扩展由
explorer.exe
进程加载,如果没有特定的Explorer配置,则需要强制退出explorer.exe
进程,以便安装新版本的Shell扩展。有一种方法可以让Explorer卸载它不再使用的DLL,但你应该只在开发机器上这样做,而不是在部署目标上:-
在RegEdit中,浏览到以下键:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
-
添加一个名为"AlwaysUnloadDLL"的新DWORD键,并将其值设置为1。
-
重新启动资源管理器。
这在大多数情况下都有效,但有时可能仍然需要关闭Explorer,因为Shell扩展程序没有卸载。
-
-
请记住,您的Shell Extension可能会被其他应用程序加载,例如,如果您右键单击具有应用程序"打开文件"对话框的文件,则您的Shell Extensions将加载到该应用程序中,而不是Explorer中。
-
如果您的Shell Extension导致运行时错误,通常情况下,结果只是您的上下文菜单项没有显示,很少会告诉您Shell Extension加载失败或导致运行时出错。
-
配置可能很困难,即使安装了,注册表数据也需要在多个位置创建,并且根据上下文菜单的显示位置,不同版本的Windows在注册表中的位置可能不同。
您需要做的事情:
- Visual Studio提供了一些创建Shell扩展的快捷方式,但基本上您需要创建一个COM DLL。上下文菜单项的Shell扩展必须同时实现
IContextMenu
接口和IShellExtInit
接口 - 在
IShellExtInit::Initialize()
方法中,可以从IDataObject
参数中获取选定的文件。从内存中,数据是"Drag-n-Drop"格式的,因此您需要从IDataObject
中获取HDROP
句柄,并从中查询文件(这是从内存中获取的,实际上可能与我在这里描述的不同,因此请谨慎操作) - 一旦您的DLL准备好"安装",您必须将其复制到某个位置,然后运行
regsvr32
以确保它已注册 - 按照本指南了解将注册表项放在哪里
- 64位Windows可能存在问题,如果您构建32位DLL,它可能无法在64位资源管理器中加载…因此,如果您在64位Windows中遇到问题,请记住这一点
- 你的DLL实际上会有两个GUID与之关联。我记不清它是如何工作的,但一个GUID指的是DLL本身,另一个指的是实际的Shell扩展。在注册表中创建需要GUID的项时,请确保使用实际Shell扩展的GUID
综合考虑…(太长了,读不下去了)
权衡Shell扩展是否值得。如果你想根据所选文件动态创建菜单项,那么Shell扩展可能是唯一的方法。如果您想同时处理所有文件,那么您可能还需要一个Shell扩展插件。
上下文菜单方法的替代方法可以是在用户的桌面上设置一个drag-n-drop目标或其他什么。探索让用户将文件提交到应用程序的其他方法,因为Shell扩展的工作量往往远远超过它的价值。我发现这是一条艰难的道路,我想其他人也一样。
- 是否可以通过C++扩展强制多个python进程共享同一内存
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 如何通过cpp程序运行shell脚本
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 扩展光电二极管探测器以支持多个传感器
- 在Windows Shell名称空间扩展程序下使用_WOPEN()
- 在 Windows 7 64 位中使用 32 位 shell 扩展
- Windows Shell 扩展没有提供确切的文件路径
- 资源管理器在 TILE 视图模式下不显示 shell 命名空间扩展的项目详细信息
- 切割和粘贴后监视文件(Windows shell扩展?)
- Windows Shell 扩展:当选择超过 16 个文件时,上下文菜单
- 在发布模式下调试shell扩展
- 加载和卸载 shell 扩展库
- 如何使用基于 IExecuteCommand 的 shell 扩展将某些上下文菜单选项变灰
- 我们是否可以强制 shell 扩展显式调用 IShellIconOverlayIdentifier::GetOverla
- 如何用C++编写shell扩展
- 将重点放在从c++ Shell扩展启动的c# UI应用程序上
- 注册特定文件类型的Shell扩展
- Shell扩展窗口:最好的通信之间的ContextMenu和IconOverlay