tags:

views:

85

answers:

2

Edit: Looks like Jon Skeet had some similar questions: http://stackoverflow.com/questions/1093536/how-does-the-c-compiler-detect-com-types

How can I get the CLSID for a given interface within a Primary Interop Assembly? Here's what I'm talking about:

// The c# compiler does some interesting magic.
// The following code ...
var app = new Microsoft.Office.Interop.Outlook.Application();

// ... is compiled like so (disassembled with Reflector):
var app =((Microsoft.Office.Interop.Outlook.Application)
  Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("0006F03A-0000-0000-C000-000000000046"))));


Microsoft.Office.Interop.Outlook.Application is an interface, and therefore it cannot be instantiated directly. What's interesting here is that c# lets you treat these COM interfaces as if they were classes that you can instantiate with the new keyword.

What I want to know is, given the System.Type for a given interface, how can I get the CLSID?

Note: I ultimately want to be able to create an instance given the interface's System.Type - I don't really care how. I'm assuming here that the easiest way to do this would be to get CLSID given the Type, just as the c# compiler does.

A: 

Try the GUID property.

SLaks
I tried that, but that doesn't give me the correct GUID, as in the following: `typeof(Outlook.Application).GUID != Type.GetTypeFromCLSID(new Guid("0006F03A-0000-0000-C000-000000000046")).GUID`.
Charles
A: 

Here's my current solution:

// Get the PIA assemby name, using the GUID of the typlib
string asmName;
string asmCodeBase;
var conv = new System.Runtime.InteropServices.TypeLibConverter();
conv.GetPrimaryInteropAssembly(new Guid("00062FFF-0000-0000-C000-000000000046"), 9, 3, 0, out asmName, out asmCodeBase);

// Load the PIA, and get the interface type
var assembly = System.Reflection.Assembly.Load(asmName);
var type = assembly.GetType("Microsoft.Office.Interop.Outlook.Application");

// Get the coclass
var coClassAttr = (System.Runtime.InteropServices.CoClassAttribute)
    type.GetCustomAttributes(typeof(System.Runtime.InteropServices.CoClassAttribute), false)[0];
var coClass = coClassAttr.CoClass;

// Instantiate the coclass
var app = Activator.CreateInstance(coClassAttr.CoClass);

// If needed, the CLSID is also available:
var clsid = coClass.GUID;

I figured this out by disassembling the GAC'd PIA. I noticed that Outlook.Application was decorated with a CoClassAttribute, like so:

[ComImport, Guid("00063001-0000-0000-C000-000000000046"), CoClass(typeof(ApplicationClass))]
public interface Application : _Application, ApplicationEvents_11_Event
{
}

ApplicationClass looks something like:

[ComImport, ClassInterface((short) 0), ComSourceInterfaces("Microsoft.Office.Interop.Outlook.ApplicationEvents_11\0Microsoft.Office.Interop.Outlook.ApplicationEvents\0Microsoft.Office.Interop.Outlook.ApplicationEvents_10\0"), Guid("0006F03A-0000-0000-C000-000000000046"), TypeLibType((short) 11)]
public class ApplicationClass : _Application, Application, ApplicationEvents_11_Event, ApplicationEvents_Event, ApplicationEvents_10_Event
{
    //...
}

Let me know what you all think, so I can decide if I should mark this as the chosen answer.

Charles