Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ComImport in C#, how do you find GUID for classes like IFileDialog in shell32.dll?

Tags:

c#

.net

guid

com

I've been trying to setup some interop with some win32 classes in various dlls using ComImport for a C# application I'm writing. What I don't understand is how you find the GUID for a class? I found some examples of imports that work but I'm not sure how the authors found the GUID for the classes. An example of importing IFileDialog and one of its methods is listed below.

[ComImport(), Guid("42F85136-DB7E-439C-85F1-E4075D135FC8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IFileDialog {
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    [PreserveSig()]
    uint Show([In, Optional] IntPtr hwndOwner); //IModalWindow

I'm using Visual Studio 2012 and I can see how to Add a reference to shell32.dll in the Microsoft Shell Controls and Automation on the COM tab but this doesn't seem to do anything for me. What am I missing here? Where do you find the GUID? Is there some way to get Visual Studio to generate the code listed above or do I need to find the GUID for each class and then write up the method import as listed above?

like image 824
bad-wulf Avatar asked Jun 12 '14 15:06

bad-wulf


1 Answers

COM servers fall into roughly two categories. The "easy" kind use a sub-set of COM called Automation. It was originally designed as the extension model for Visual Basic version 4. Wildly successful, practically any language runtime on Windows supports it. You typically recognize them from their interfaces inheriting from IDispatch.

They are easy most of all because they support a type library. Which is a language-independent description of the interfaces supported by the server, including their guids. Type libraries are just like metadata in .NET. And used the same way, a compiler can read it and know how to perform type-checking on your code and provide auto-completion. Shell32.dll has one, it is embedded inside the DLL as a resource. It is very limited, only intended to give scripting languages access to some of the shell functionality.

Then there's the "hard" kind. You typically recognize them from their interfaces inheriting from IUnknown. They are only easy to use from C++, there is no type library for them and you can't create one either because they tend to use types that are not Automation compatible. Major chunks of Windows are only usable with such interfaces, the shell and DirectX are the best known examples. You can use them from C# but you have to write the [ComImport] interface by hand, like you did.

The declarations for these interfaces are present in .h files in the Windows SDK. Most programmers have version 7.1 on their machine, depending on their VS version, located in c:\program files (x86)\microsoft sdks\windows\v7.1a\include. So a simple thing you can do is use the Edit + Find and Replace + Find in Files menu command in VS and search the directory for "IFileDialog". Out pops:

  MIDL_INTERFACE("42f85136-db7e-439c-85f1-e4075d135fc8")
  IFileDialog : public IModalWindow
     // etc...
  }

Why it inherits from IModalWindow instead of IUnknown and you never mention it in your C# declaration is a story for another day :)

like image 85
Hans Passant Avatar answered Sep 27 '22 22:09

Hans Passant