如何用C++编写shell扩展?

voi*_*ter 17 c++ atl windows-shell shell-extensions

这似乎是一个常见的问题,但经过一些搜索后,我真的无法找到答案.这里有一篇文章:

http://www.codeproject.com/KB/shell/shellextguide1.aspx

但它适用于Visual Studio的旧版本.我正在使用VS 2008,所以说明和界面似乎与我所看到的不相符.

我想使用C++创建一个简单的shell扩展,为扩展名为.GZ的文件创建上下文菜单.当右键单击这些文件时,我应该能够单击我的上下文菜单项并在代码中进行回调以对该文件执行某种操作.

其他上下文菜单项将执行诸如生成无模式对话框之类的操作,以在执行某些操作之前接受用户输入.

从我所看到的,ATL用于此,但我从未使用过ATL,所以所有的对象类型和接口都让我很困惑.如果我有适当的教程或文档可供阅读,那就不会那么糟糕了.

谁能帮我吗?是不是有一些不是10年的教程?

dre*_*lax 24

我无法确切地告诉你如何编写shell扩展,但我会提供一些提示.编写Shell扩展比简单的"仅限注册表"方法提供了一些显着优势:

  • 使用Shell扩展,您可以动态创建与所选文件更相关的上下文菜单项(或子菜单).例如,如果您正在为zip文件编写Shell扩展,则可以在上下文菜单中创建一个子菜单,该子菜单显示zip的全部内容.
  • 您可以同时处理多个文件,这不仅有助于提高性能,还可以根据整体选择而不仅仅针对每个文件来确定要做的事情.

Shell Extensions的一些缺陷是:

  • 大大增加了复杂性.准备好花费大量精力来实现它.在您的计算机旁安装家用浓缩咖啡机和/或雇用某人为您做咖啡.

  • 调试的难度大大增加.同样关于咖啡.

编写Shell扩展很困难,因为它们很难调试.

  • Shell Extensions由explorer.exe进程加载,如果没有Explorer的特定配置,您需要强制退出该explorer.exe进程,以便可以安装较新版本的Shell扩展.有一种方法可以让Explorer卸载它不再使用的DLL,但是您应该只在开发机器上而不是在部署目标上执行此操作:

    1. 在RegEdit中,浏览到以下键:

      HKEY_LOCAL_MACHINE\SOFTWARE \微软\的Windows\CurrentVersion\Explorer中

    2. 添加一个名为"AlwaysUnloadDLL"的新DWORD键,并将其值设置为1.

    3. 重启资源管理器.

    这在大多数情况下都有效,但有时您可能需要关闭资源管理器,因为未卸载Shell扩展.

  • 请记住,其他应用程序可能会加载Shell扩展,例如,如果右键单击带有应用程序"打开文件"对话框的文件,则Shell扩展将加载到该应用程序中,而不是资源管理器.

  • 如果Shell扩展导致运行时错误,通常结果只是您的上下文菜单项未显示,很少会被告知您的Shell扩展无法加载或导致运行时错误.
  • 配置可能很难,即使安装,需要在多个位置创建注册表数据,并且根据您希望上下文菜单显示的位置,注册表中的位置可能在不同版本的Windows之间有所不同.

你需要做什么:

  • Visual Studio提供了一些创建Shell Extensions的快捷方式,但基本上您需要创建一个COM DLL.上下文菜单项的Shell扩展必须同时实现IContextMenu接口和IShellExtInit接口.
  • 在该IShellExtInit::Initialize()方法中,您可以从IDataObject参数中获取所选文件.从内存中,数据采用"Drag-n-Drop"格式,因此您需要从中获取HDROP句柄并从中IDataObject查询文件(这是来自内存,它实际上可能与我在此处描述的不同,因此请继续慎用).
  • 一旦您的DLL准备好"安装",您必须将其复制到某个地方,然后运行regsvr32以确保它已注册.
  • 请按照本指南了解放置注册表项的位置.
  • 可能会出现问题与64位Windows,如果你建立一个32位的DLL它可能无法在64位浏览器加载...因此,如果您在使用64位Windows的麻烦记住这一点.
  • 您的DLL实际上有两个与之关联的GUID.我不记得它是如何工作的,但是一个GUID引用DLL本身而另一个引用实际的Shell扩展.在需要GUID的注册表中创建密钥时,请确保使用实际Shell扩展的GUID.

考虑到所有事情......(tl; dr)

权衡Shell扩展是否值得的成本.如果要根据所选文件动态创建菜单项,则Shell扩展可能是唯一的方法.如果你想同时处理所有文件,那么你可能也需要一个Shell扩展.

上下文菜单方法的替代方法可以是在用户的桌面上具有拖放目标或其他东西.探索可以让用户将文件提交到应用程序的其他方式,因为Shell扩展通常比它的价值要大得多.我发现这很困难,我认为其他人也都有.

  • +1令人敬畏的帖子,使用.NET 4,事情变得更容易了,您现在可以在托管代码中编写shell扩展.在这里提到它,所以人们不会完全被劝阻. (3认同)