如何在资源管理器中双击文件被钩住?

Posted

技术标签:

【中文标题】如何在资源管理器中双击文件被钩住?【英文标题】:How can double-clicking a file in explorer be hooked? 【发布时间】:2014-05-13 16:49:16 【问题描述】:

当用户双击文件启动它时,如果文件符合特定条件,我需要执行自定义操作。

在 WindowsXP 中,可以使用 detours 来挂钩 explorer.exe 中的 ShellExecuteEx,并且可以访问文件名。我需要在 Windows 7 和 8 中做类似的事情。

如何在双击文件时执行一些代码,并获得文件名?

我需要一种在 Windows 更新补丁资源管理器中继续有效的方法。

【问题讨论】:

只有当它们被双击或仅仅当它们被打开外壳时?看看 HKCR 并将您的程序放在适当的动词中。另外,这样做时要小心谨慎,否则您的程序很容易成为这片土地上的瘟疫。 这听起来是个坏主意。如果您能告诉我们那是什么,那么可能有一种适当的方法可以完成您想要实现的任何目标。 为什么 Detours 在 Windows 7 中停止工作? @Deduplicator 当 shell 打开时。我想处理所有文件类型的所有动词。 @Cody Gray - explorer.exe 不再在内部调用 ShellExecuteExW。 【参考方案1】:

使用procmon 进行的简短检查表明,每次资源管理器激活文件时(通过双击或按回车键)。资源管理器搜索HKCR\*\ShellEx\DataHandler

DataHandler 是windows shell extensions 的多种类型之一。

因此,虽然文档声明它用于拖放操作,但它似乎总是在 打开一个文件。

我已经按照How to Create Data Handlers 教程进行了如何注册一个,只是做了一个小改动:我在HKCR\*\ShellEx\DataHandler 下添加了DataHandler,带有一个自定义GUID 和一个相应的CLSID 条目并链接了它到一个什么都不做的dll。现在每次我单击或“输入”文件时都会加载它。我没有实现所有必需的接口,但根据文档:

Shell 通过其 IPersistFile 接口初始化处理程序。 它使用这个接口来请求处理程序的类标识符 (CLSID) 并为其提供文件名

所以理论上它应该可以被实现所需接口的 dll 访问,并且您可以在每次访问时访问文件名并执行自定义操作而不做其他任何事情。

我目前没有时间自己编写这样的 dll(可能稍后),但它看起来是一个不错的方向,您可以探索。

【讨论】:

这是非常不可靠的。 DataHandler 是任何程序都可以使用的开放接口。 Windows Shell 本身多次调用它(例如右键单击文件以显示上下文菜单),而不仅仅是在您执行基础文件时。如果在 Windows Shell 中安装了自定义扩展(许多),情况可能会变得更糟,因为它们可能会出于其他原因使用它。【参考方案2】:

所以基本上你想做防病毒软件的工作,对吧?拦截所有 I/O 调用?你想要一个名为filters 的东西(我上次使用它是在我的旧 XP 机器上)。如果您不想编写自己的驱动程序,过滤器是您的最佳选择!

这比所有那些讨厌的 API 挂钩要好得多。 From MSDN:

你看到那个“Minifilter A”了吗?这可能是你接下来几天想去的地方!

【讨论】:

【参考方案3】:

有点超出我的深度,但这里是。我很久以前读过一些东西,每次双击应用程序时,资源管理器都会调用SHELL32!CExecuteApplication::Execute。但是,没有关于它的真实文档。如果您跟踪调用,它最终会调用CreateProcess。我想你可以钩住它。但是,如果应用程序已经在运行并且它是单实例应用程序(例如 MS Outlook),CreateProcess 将不起作用。仅当资源管理器需要创建进程时才会调用此函数。

【讨论】:

可能没用。并非每次双击都会产生一个新进程——“打开”操作可能由系统处理,向相应应用程序的已打开实例发送消息。 我知道这是一个远大的目标,但由于没有其他人说过类似的话,我认为它在某种程度上可能对 Scott 有用。【参考方案4】:

当我尝试将所有执行调用挂钩到特定驱动器号时,我遇到了类似的问题。最初,我将 shellexecuteex 与 detour 库挂钩。这在 Windows 7 中失败,因为资源管理器开始使用直接 kernel32.dll 或 ntdll 等效调用跳过 shell API 层。 处理应用程序执行的自定义处理的更好方法是实现 shell 文件夹。我通过添加注册表项来隐藏实际的驱动器号。然后我实现了一个 shell 文件夹,它显示隐藏的驱动器号内容的内容。通过这种方法,我能够更好地控制资源管理器中显示的项目,最终捕获双击。尽管您需要编写大量代码以使 UI 与资源管理器相同,但对于您的要求,这是更合适且更恰当的文档化方法。

【讨论】:

以上是关于如何在资源管理器中双击文件被钩住?的主要内容,如果未能解决你的问题,请参考以下文章

双击时如何使Windows批处理文件暂停?

默认情况下如何在双击表单时打开代码?

我们可以在它被钩住之前将数据传递给 DLLMain 吗?

让windows决定如何打开/运行文件?

在 Visual Studio 设计器中为控件指定双击事件

如何防止执行批处理文件后自动关闭控制台