3

I am writing programs that use another Application.
Lets say the Application ProgID is TheCompany.TheProg

up untill now, i was using "Add References/COM" and selecting the TheProg Type Lib

but it was mentioned by the 3ed party vendor that creating Interop DLLs is not supported and can cause some interface changes with version upgrades.

my question is: How can i reference this TheCompany.TheProg COM+ object without the creation of the Interop DLL?

I know i can use

Type theProgType = Type.GetTypeFromProgID("TheCompany.TheProg");
dynamic myObject = Activator.CreateInstance(theProgType);
dynamic version = myObject.AMethod();

but: 1. i need to cast Everything dynamic which require .NET FW v4!
unless i want to use theProgType.InvokeMethod() :)
2. I Have no IntelliSense.

Thanks a lot

Tomer W
  • 3,395
  • 2
  • 29
  • 44

1 Answers1

2

Can't help myself giving a late answer to this question, as I just dealt with a similar thing.

Basically, you could define your own subset of their interfaces to be used via late binding only, here's how:

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] // late binding only
[Guid("00020400-0000-0000-C000-000000000046")] // IDispatch's GUID
interface IMyLateBindingAdaptor
{
    // a subset of IWebBrowser2 [http://msdn.microsoft.com/en-us/library/aa752127(v=vs.85).aspx]
    string LocationURL { get; }
    void Navigate(string url, ref object flags, ref object TargetFrameName, ref object PostData, ref object Headers);
}

Make sure the names and signatures of the defined properties and method match the specification from your vendor.

Using it:

var adaptor = this.webBrowser1.ActiveXInstance as IMyLateBindingAdaptor;
if (null == adaptor)
    throw new ApplicationException("No late binding.");
object missing = Type.Missing; // VT_EMPTY
adaptor.Navigate("http://www.example.com", ref missing, ref missing, ref missing, ref missing);
MessageBox.Show(adaptor.LocationURL);

In my opinion, it's better than dynamics as it gives you compile-time type safety (sort of) and IntelliSense.

noseratio
  • 59,932
  • 34
  • 208
  • 486
  • 1. isn't that exactly like using the TLBImp tool for creating the Interop.Dll ? – Tomer W Aug 21 '13 at 13:17
  • 1
    No. Unlike with TLBImp, with this approach there is **no explicit bindings** to any of the APIs from your vendor, **besides names themselves**. No numeric DISPIDs either, so C# will call [IDispatch::GetIDsOfNames](http://msdn.microsoft.com/en-us/library/ms221306(v=vs.85).aspx) during runtime whenever it needs to resolve a new name. Your vendor may change the order of methods, GUIDs, DISPIDs, or add new methods. But as long as they keep the method names and arguments the same for existing methods, your code should work without recompilation. You just drop in the new COM Server DLL. – noseratio Aug 21 '13 at 13:27
  • ok, good to know, my TLB has over 100 classes with avg of 50 public members, is there a tool (similar to TLBImp) that will construct this code automatically ? – Tomer W Aug 21 '13 at 13:34
  • I'm not aware of an automatic tool like that. [This](http://stackoverflow.com/a/6203117/1768303) post may be useful. – noseratio Aug 21 '13 at 13:50
  • 1
    Still dont know about if it will create this exactly, but take a look at http://clrinterop.codeplex.com/releases/view/17579 it is a more flexible `TLBIMP` tool – Tomer W Aug 22 '13 at 08:07
  • The open-sourced TLBIMP is a great tool, but IMO, you'd need to customize it significantly to generate interfaces like above. – noseratio Aug 22 '13 at 08:09
  • omg i try your idea and i am failing to do so... 1. created a Interop.dll with TLBIMP 2. decompiled the DLL 3. edited the interfaces: remove DISPID(##) and set the IDispatch. i use `MyInterface iface = (MyInterface)Activator.CreateInstance(Type.GetFromProgId("blah.bla");` but i get an Exception of "No such interface supported". any idea? – Tomer W Aug 22 '13 at 10:13
  • 1
    Make sure the `GUID` of your `MyInterfaces` is exactly this: `[Guid("00020400-0000-0000-C000-000000000046")]` (the one of IDispatch). I expect TLBIMP to generate a different one, make sure to change it to the above. – noseratio Aug 22 '13 at 10:18
  • 2
    Ahhhhhhh!!!! NOW I GET YOUR POINT! :) you make the class derive from IDispach, and not the original GUID... well done... working but needs much work to get done :\ – Tomer W Aug 22 '13 at 12:54
  • 1
    Yep, that's the trick to purely late binding :] Glad it worked it out for you! – noseratio Aug 22 '13 at 12:58