如何用 C++ 编写 shell 扩展?
这似乎是一个常见问题,但经过一些搜索后,我并没有真正找到答案。这里有一篇关于此的文章:
http://www.codeproject.com/KB/shell/shellextguide1.aspx< /a>
但它适用于非常旧版本的 Visual Studio。我使用的是 VS 2008,所以说明和界面似乎与我所看到的不符。
我想使用 C++ 创建一个简单的 shell 扩展,为扩展名为 .GZ 的文件创建上下文菜单。右键单击这些文件时,我应该能够单击上下文菜单项并在代码中进行回调以对该文件执行某种操作。
其他上下文菜单项会执行诸如生成无模式对话框之类的操作,以在执行某些操作之前接受用户输入。
据我所知,ATL 用于此目的,但我从未使用过 ATL,因此所有对象类型和接口对我来说都非常混乱。如果我有合适的教程或文档可供阅读,那就不会那么糟糕了。
有人可以帮我吗?是不是有一些 10 年前的教程?
This seemed like a common question but after doing some searching, I wasn't really able to find my answers. There is an article on this here:
http://www.codeproject.com/KB/shell/shellextguide1.aspx
But it's for a very old version of Visual Studio. I'm using VS 2008, so the instructions and interfaces don't seem to match what I'm seeing.
I want to create a simple shell extension using C++ that creates a context menu for files with extension .GZ. When right clicking on these files, I should be able to click my context menu item and have a callback in code to do some sort of operation on that file.
Other context menu items would do things like spawn modless dialogs to accept user input before executing some action.
From what I've seen, ATL is used for this but I have never used ATL, so all of the object types and interfaces are very confusing to me. It wouldn't be so bad if I had a proper tutorial or documentation to read.
Can anyone help me out? Isn't there some sort of tutorial out there that isn't 10 years old?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我无法准确地告诉您如何编写 shell 扩展,但我会提供一些技巧。与更简单的“仅注册表”方法相比,编写 Shell 扩展具有一些显着的优势:
Shell 扩展的一些缺点是:
复杂性大大增加。准备好为此付出大量努力才能使其发挥作用。在计算机旁边安装一台家用浓缩咖啡机和/或雇人为您泡咖啡。
大大增加了调试难度。关于咖啡也是如此。
编写 Shell 扩展很困难,因为它们很难调试。
Shell扩展是由
explorer.exe
进程加载的,如果没有对Explorer进行特定配置,则需要强制退出explorer.exe
进程,这样您就可以安装新版本的 Shell 扩展。有一种方法可以让资源管理器卸载不再使用的 DLL,但您应该只在开发计算机上执行此操作,而不是在部署目标上执行此操作:在 RegEdit 中,浏览到以下键:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
添加一个名为“AlwaysUnloadDLL”的新 DWORD 项,并将其值设置为 1。
重新启动资源管理器。
这在大多数情况下都有效,但有时您可能仍然需要关闭资源管理器,因为 Shell 扩展未卸载。
请记住,您的 Shell 扩展可能会被其他应用程序加载,例如,如果您右键单击带有应用程序“打开文件”对话框的文件,那么您的 Shell 扩展将被加载到该应用程序中,而不是加载到该应用程序中。资源管理器。
如果您的 Shell 扩展导致运行时错误,通常结果只是您的上下文菜单项不显示,很少会告诉您您的 Shell 扩展无法加载或导致运行时错误。< /p>
配置可能很困难,即使安装了,也需要在多个位置创建注册表数据,并且根据您希望上下文菜单显示的位置,不同版本的 Windows 之间注册表中的位置可能有所不同。
您需要做什么:
IContextMenu
界面和IShellExtInit
接口。IShellExtInit::Initialize()
方法中,您可以从IDataObject
参数获取选定的文件。从内存中,数据采用“拖放”格式,因此您需要从IDataObject
获取HDROP
句柄,并从那里查询文件(这是根据记忆,它实际上可能与我在这里描述的不同,所以请谨慎行事)。考虑所有因素... (tl;dr)
权衡 Shell 扩展是否值得的成本。如果您想根据所选文件动态创建菜单项,那么 Shell 扩展可能是唯一的方法。如果您想同时处理所有文件,那么您可能还需要 Shell 扩展。
上下文菜单方法的替代方法可能是在用户桌面上放置一个拖放目标或其他东西。探索让用户将文件提交到应用程序的其他方法,因为 Shell 扩展通常需要付出的努力远远超出其价值。我通过艰难的方式发现了这一点,我想其他人也发现了这一点。
I can't tell you exactly how to write a shell extension, but I will provide a number of tips. Writing a Shell Extension offers some significant advantages over the much simpler “registry-only” method:
Some of the downfalls to Shell Extensions are:
Substantially increased complexity. Be prepared to spend a lot of effort on this to get it working. Have a home-espresso machine installed next to your computer and/or hire someone to make you coffee.
Substantially increased difficulty in debugging. Ditto about coffee.
It's difficult to write a Shell Extension because they can be very hard to debug.
Shell Extensions are loaded by the
explorer.exe
process, and without specific configuration of Explorer, you need to force-quit theexplorer.exe
process so that you can install a newer version of your Shell Extension. There is a way to get Explorer to unload DLLs that it is no longer using, but you should only do this on a development machine and not on a deployment target:In RegEdit, browse to the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
Add a new DWORD key called “AlwaysUnloadDLL” and set its value to 1.
Restart explorer.
This works most of the time, but there may still be times where you need to close Explorer because the Shell Extension was not unloaded.
Keep in mind that your Shell Extension may be loaded by other applications, for example, if you right-click on a file with an applications “open file” dialog, then your Shell Extension will be loaded into that application, and not Explorer.
If your Shell Extension causes a runtime error, quite often the result will simply be that your context menu item does not show, very rarely will you be told that your Shell Extension failed to load or that it caused a runtime error.
Configuration can be hard, even with an installation, registry data needs to be created in several places, and depending where you want your context menu to show, the places in the registry may differ between different versions of Windows.
What you'll need to do:
IContextMenu
interface and theIShellExtInit
interface.IShellExtInit::Initialize()
method, you can obtain the selected files from theIDataObject
parameter. From memory, the data is in “Drag-n-Drop” format, so you need to get anHDROP
handle from theIDataObject
and query the files from there (this is from memory, it may actually be different than as I described here, so proceed with caution).regsvr32
to make sure it is registered.All things considered… (tl;dr)
Weigh up the costs of whether a Shell Extension is worth it. If you want to create menu items dynamically based on the selected files, then a Shell Extension may be the only way. If you want to handle all files simultaneously then you'll probably need a Shell Extension as well.
An alternative to the context menu method, could be to have a drag-n-drop target on the user's desktop or something. Explore other ways that you could have the user submit your files to your application, because a Shell Extension is often far more effort than it is worth. I found this out the hard way and I think everyone else has too.