4

Is there any way of calling a DLL that is a shell extension programmatically? We use a software that registers a shell extension on windows explorer, and I need to call one of the items available on its context menu. I do not have the software source code that I want to call.

EDIT

This context menu only appears when I select a PDF file on windows explorer. So i need to call it passing a dll file.

EDIT

Registry information:

[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}\Programmable]

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

EDIT

Is it possible to call ShellExecuteEx with the verb i want (not the default one)? If so, how do I call the verb I want (which uses the DLL)?

Thats the verb i wanna call for a PDF file:

enter image description here

Rafael Colucci
  • 6,018
  • 4
  • 52
  • 121
  • What does the shell extension do? What type of extension is it? – David Heffernan Apr 19 '11 at 19:45
  • It works in a pdf file. I guess it is a COM DLL, but i am not sure. – Rafael Colucci Apr 19 '11 at 19:46
  • You need to know what sort of shell extension it is in order to know how to call it. If you don't know what type it is then how will you know which COM interfaces to ask for? – David Heffernan Apr 19 '11 at 19:49
  • This software is not mine. That is why I am asking it on stack overflow. – Rafael Colucci Apr 19 '11 at 19:50
  • 1
    You won't get an answer until you work out what sort of shell extension it is. There are lots of different types of shell extension. – David Heffernan Apr 19 '11 at 19:52
  • So, how can I work out what kind it is if I dont know its source code: – Rafael Colucci Apr 19 '11 at 19:53
  • @Rafael you can see how it is registered in the registry under HKCR. Do you know what a shell extension is? I don't think you do. I think you should read up and find out otherwise this question will become a disaster zone. – David Heffernan Apr 19 '11 at 19:55
  • Yeah, I know what a shell extension is. I guess this dll is a COM, as I told you. I posted the registry info. – Rafael Colucci Apr 19 '11 at 20:02
  • Look up the CLSID values on the web and work it out from there. – David Heffernan Apr 19 '11 at 20:04
  • Look up `HKCR\.pdf` and see that the value of `(Default)` is, let's call it ``. Then look up `HKCR\`, and so on. – David Heffernan Apr 19 '11 at 20:20
  • From the registry excerpt you posted it looks like the shell extension comes with ABBYY PDF Transformer 3.0. Maybe the main program has command line parameters that let you perform your task. – Uli Gerhardt Apr 19 '11 at 20:22
  • Unless the case you mentioned with ABBYY PDF Transformer is just as a generic example, what you are trying to do here is very likely to violate the license of this software, especially if you are planning to distribute what you are developing. ABBYY provides other products that are meant to be used programmatically, take a look at ABBYY OCR SDK - http://www.abbyy.com/ocr_sdk – yms Apr 19 '11 at 22:27
  • 1
    By the way, +1 to compensate for someone who down-voted without leaving any comment. – yms Apr 19 '11 at 22:31
  • @yms it is a generic example. The real program is one that we lost the source code long time ago and it was created by us. – Rafael Colucci Apr 19 '11 at 23:00

3 Answers3

11

The DLL is evidently a context-menu extension. If you want to call it the same way the shell does, then you want to host the IContextMenu interface that the DLL implements. Several years ago, Raymond Chen wrote an extensive series on this topic:

How to host an IContextMenu

  1. Initial foray
  2. Displaying the context menu
  3. Invocation location
  4. Key context
  5. Handling menu messages
  6. Displaying menu help
  7. Invoking the default verb
  8. Optimizing for the default command
  9. Adding custom commands
  10. Composite extensions - groundwork
  11. Composite extensions - composition

The first two articles are the most important. They introduce how to get the IContextMenu interface of a file in the first place, and then how to invoke one or more of the commands offered by that menu. Essentially, get the IContextMenu interface, fill a CMINVOKECOMMANDINFOEX structure, and then pass it to the interface's InvokeCommand method. The articles call TrackPopupMenu to display a menu to the user, and then use the selection to fill the structure, but if you already know exactly which command you want to run, then you can forgo displaying the menu. (You might still have to create the menu, though, since the IContextMenu object probably expects to have QueryContextMenu called on it first.)

Community
  • 1
  • 1
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Why can't he just call ShellExecuteEx? – David Heffernan Apr 19 '11 at 21:08
  • 4
    No idea, @David. He asked how to *call the DLL* — but I guess you know from experience that answering the question *as asked* can get us into trouble. But even if he does use ShellExecuteEx, he'll still have to go through this procedure once to find out what verbs are available since they're not in the registry. – Rob Kennedy Apr 19 '11 at 21:17
  • Its ok if somebody show me how to call the context menu by using ShellExecuteEx. I am studying the links you posted, but i have nothing working yet. – Rafael Colucci Apr 19 '11 at 22:15
6

Rafael, you can use the IContextMenu Interface. from here you can enumerate the entries returned by the interface and then execute the option which you want using the InvokeCommand

RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • Sounds nice, but i am new to c#. Can you provide me a sample or a Delphi code please? – Rafael Colucci Apr 19 '11 at 20:47
  • 2
    Check this question http://stackoverflow.com/questions/3777121/how-to-access-windows-shell-context-menu-items and the Craig Peterson answer. – RRUZ Apr 19 '11 at 20:49
  • @RRUZ http://stackoverflow.com/questions/3777121/how-to-access-windows-shell-context-menu-items – Rafael Colucci Apr 19 '11 at 22:13
  • @Rafael, first i don't post any code in this link only suggestions, the code posted is from Craig Peterson. this code can guide you to solve your problem, if don't work as you expect you can post a new question in S.O with the code included to help you , showing the part `which not work` for you. – RRUZ Apr 19 '11 at 22:27
  • @RRUZ, sorry. I meant the source on the link you posted. – Rafael Colucci Apr 19 '11 at 23:24
2

It's a COM object. You just need to create it, and pass it interfaces (with enough implementation behind it) it make it work.

Explorer (i.e. you) will ask the shell extension to add items to an different HMENUs. Then Explorer (i.e. you) invokes a menu item in response to the user.

Fortunately everything in the shell is an interface - so you can pretend to be whatever you want. You just need to read the SDK contract from the other side.

Remember: A shell extension doesn't have to be hosted in Explorer. Many aren't. A lot are hosted in the "Save As" dialog from CommCtrl.


In your case it's even simpler.

  • Create the COM Object
  • query for its IShellExtInit interface, and call .Initialize.
  • query for its IContextMenu interface
  • call IContextMenu.QueryContextMenu, allowing it to add items to an HMENU
  • call IContextMenu.Invoke

Again, a case of reading the contract from the other side.


Some pseudo-code:

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);

That's as far as i get from reading documentation and guessing what to do. Now i have to pee, and go home to play Portal 2

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • I guess i have no knowledge to do that. Maybe somebody can show me how to use ShellExecuteEx to call the verb. But thanks for your help. – Rafael Colucci Apr 19 '11 at 20:45