5

I'm writing an application for the Peachtree API and it needs to work with any version of the API. Unfortunately the dll from Peachtree 2011 can't interact with Peachtree 2010, and vice versa, even though the two dlls are stored in the same location and run with exactly the same code.

I thought I should be able to refer to the dll by it's file path, leave specific version at false, embed interop types at false, and copy local at false and it would just use whatever version the machine had, but I get an error when I do that - "Exception has been thrown by the target of an invocation."

Is there a way to late-bind the dll even though it's COM?

I can provide code samples of whatever you think would be helpful, but it's more of a project setup issue than anything.

EDIT: Thank you all very much for your help. I found my solution on a different person's question and posted it here.

Yoenhofen
  • 397
  • 5
  • 12
  • Usually you link the interop DLL at compile time, and if it is present on the system, it will load the COM dll at runtime. Is there any more information in the error, or an inner exception? Is there an error code (0xZZZZZZZZ)? Can you link the stack trace, or is that giving too much info about your app? The Peachtree API, is it COM, or is it a DLL that links to COM? – Merlyn Morgan-Graham Aug 31 '10 at 18:04

2 Answers2

7

Late-binding to COM objects requires that you do NOT add a reference to the COM library to your .NET project. Instead, you should you use something like this to create COM objects:

   Type type = Type.GetTypeFromProgID("Excel.Application")
   object app = Activator.CreateInstance(type);

Then, it will bind to any version of the COM library at runtime.

See this article for more details.

  • 1
    and with .net 4.0 you can use the new `dynamic` type and have late method call binding, eliminating the need to add a type reference http://msdn.microsoft.com/en-us/library/dd264736.aspx – Remus Rusanu Aug 31 '10 at 18:59
  • One thing I'd like to add is that, when you get the object from create instance, you can cast it to the right interface type, so you still have static binding, even though though creation is late-bound. – zumalifeguard Aug 31 '10 at 19:39
  • Great article in the link! Thak you so much! – horgh Sep 26 '13 at 09:53
0

This is the solution

Compile a version agnostic DLL in .NET

In case that link ever dies, the key is to handle the AppDomain.CurrentDomain.AssemblyResolve event like below. The event fires any time an assembly binding fails, so you can resolve it yourself, fixing version conflicts.

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}
Community
  • 1
  • 1
Yoenhofen
  • 397
  • 5
  • 12