4

有没有办法以编程方式调用作为 shell 扩展的 DLL?我们使用在 Windows 资源管理器上注册 shell 扩展的软件,我需要调用其上下文菜单中可用的项目之一。我没有想要调用的软件源代码。

编辑

此上下文菜单仅在我在 Windows 资源管理器中选择 PDF 文件时出现。所以我需要调用它传递一个dll文件。

编辑

注册表信息:

[HKEY_CLASSES_ROOT\CLSID{2DC8E5F2-C89C-4730-82C9-19120DEE5B0A}] @="PDFTransformer3.PDFTContextMenu.1"

[HKEY_CLASSES_ROOT\CLSID{2DC8E5F2-C89C-4730-82C9-19120DEE5B0A}\InprocServer32] @="C:\Program Files\ABBYY PDF Transformer 3.0\PDFTContextMenu.dll" "ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\CLSID{2DC8E5F2-C89C-4730-82C9-19120DEE5B0A}\ProgID] @="PDFTransformer3.PDFTContextMenu.1"

[HKEY_CLASSES_ROOT\CLSID{2DC8E5F2-C89C-4730-82C9-19120DEE5B0A}\可编程]

[HKEY_CLASSES_ROOT\CLSID{2DC8E5F2-C89C-4730-82C9-19120DEE5B0A}\VersionIndependentProgID] @="PDFTransformer3.PDFTContextMenu"

编辑

是否可以ShellExecuteEx使用我想要的动词(不是默认动词)调用?如果是这样,我如何调用我想要的动词(使用 DLL)?

那就是我想调用PDF文件的动词:

在此处输入图像描述

4

3 回答 3

11

DLL 显然是一个上下文菜单扩展。如果您想以与 shell 相同的方式调用它,那么您需要承载DLL 实现的 IContextMenu 接口。几年前,Raymond Chen 就这个话题写了一篇内容丰富的系列文章:

如何托管 IContextMenu

  1. 初步尝试
  2. 显示上下文菜单
  3. 调用位置
  4. 关键背景
  5. 处理菜单消息
  6. 显示菜单帮助
  7. 调用默认动词
  8. 优化默认命令
  9. 添加自定义命令
  10. 复合扩展 - 基础
  11. 复合扩展 - 复合

前两篇文章是最重要的。他们首先介绍了如何获取文件的 IContextMenu 接口,然后介绍了如何调用该菜单提供的一个或多个命令。本质上,获取 IContextMenu 接口,填充 CMINVOKECOMMANDINFOEX 结构,然后将其传递给接口的InvokeCommand方法。文章调用TrackPopupMenu向用户显示菜单,然后使用选择来填充结构,但如果您已经确切知道要运行哪个命令,那么您可以放弃显示菜单。(不过,您可能仍然需要创建菜单,因为 IContextMenu 对象可能希望首先QueryContextMenu调用它。)

于 2011-04-19T21:04:30.300 回答
6

Rafael,你可以使用IContextMenu接口。从这里您可以枚举接口返回的条目,然后使用InvokeCommand

于 2011-04-19T20:43:56.330 回答
2

它是一个 COM 对象。您只需要创建它,并将其传递给它的接口(背后有足够的实现)它就可以工作。

Explorer(即您)将要求外壳扩展将项目添加到不同的 HMENU。然后资源管理器(即您)调用一个菜单项以响应用户。

幸运的是,shell 中的所有东西都是一个接口——所以你可以假装成你想要的任何东西。您只需要从另一端阅读 SDK 合同

请记住Shell 扩展不必托管在 Explorer。许多不是。CommCtrl 的“另存为”对话框中有很多内容。


在您的情况下,它甚至更简单

  • 创建 COM 对象
  • 查询其IShellExtInit接口,并调用.Initialize.
  • 查询其IContextMenu接口
  • 调用IContextMenu.QueryContextMenu,允许它添加项目到HMENU
  • 称呼IContextMenu.Invoke

再次,从另一方阅读合同的案例。


一些伪代码:

var
   ClassID: TGUID;
   unk: IUnknown;
   shellext: IShellExtInit;
   dataObject: IDataObject;
   hkeyProgID: HKEY;
   contextMenu: IContextMenu;
   commandInfo: CMINVOKECOMMANDINFO;
begin
   ClassID := ProgIDToClassID('PDFTransformer3.PDFTContextMenu'); 
   unk := CreateComObject(ClassID);

   shellExt := unk as IShellExtInit;

    {
       For shortcut menu extensions, 
          pdtobj identifies the selected file objects,
          hkeyProgID identifies the file type of the object with focus, and 
          pidlFolder is either NULL (for file objects) or specifies the folder 
             for which the shortcut menu is being requested 
             (for folder background shortcut menus).
   }
   shellExt.Initialize(
         nil, //pidlFolder, null for file objects
         dataObject, //IDataObject of the selected file
         hkeyProgID); //HKEY of the file type of the object with focus    

   contextMenu := unk as IContextMenu;
   contextMenu.QueryContextMenu(
         menuHandle, //HMENU, A handle to the shortcut menu. The handler should specify this handle when adding menu items.
         0, //integer, The zero-based position at which to insert the first new menu item.
         100, //The minimum value that the handler can specify for a menu item identifier.
         200, //The maximum value that the handler can specify for a menu item identifier.
         CMF_NORMAL); //optional flags

   contextMenu.InvokeCommand(commandInfo);

这是我从阅读文档和猜测该怎么做中得到的。现在我要尿尿,然后回家玩传送门 2

于 2011-04-19T20:43:14.590 回答