在运行时加载一个COM dll?

5
我正在为Peachtree API编写应用程序,需要与任何版本的API一起工作。不幸的是,来自Peachtree 2011的dll不能与Peachtree 2010交互,反之亦然,即使这两个dll存储在相同位置并使用完全相同的代码运行。
我认为我应该能够通过文件路径引用dll,将特定版本设置为false,将嵌入式交互类型设置为false,并将复制本地设置为false,它将使用机器上拥有的任何版本,但是当我这样做时,会出现错误 -“目标对象的调用已引发异常。”
即使它是COM,是否有一种方法可以延迟绑定dll?
我可以提供您认为有帮助的代码示例,但这更多是一个项目设置问题。
编辑:非常感谢大家的帮助。我在另一个人的问题中找到了解决方案,并在此处发布了它。

通常情况下,您在编译时链接Interop DLL,如果系统上存在该DLL,则会在运行时加载COM dll。错误信息中是否有更多信息或内部异常?是否有错误代码(0xZZZZZZZZ)?您能否链接堆栈跟踪,或者这会给出关于您的应用程序太多的信息?Peachtree API是COM还是链接到COM的DLL? - Merlyn Morgan-Graham
2个回答

7
晚期绑定到COM对象需要您不要将COM库添加到.NET项目的引用中。相反,您应该使用类似以下内容来创建COM对象:
   Type type = Type.GetTypeFromProgID("Excel.Application")
   object app = Activator.CreateInstance(type);

然后,在运行时它将绑定到任何版本的COM库。

有关更多详细信息,请参见此文章


1
使用 .NET 4.0,您可以使用新的 dynamic 类型,并具有后期方法调用绑定,无需添加类型引用。http://msdn.microsoft.com/en-us/library/dd264736.aspx - Remus Rusanu
有一件事我想要补充的是,当你从创建实例中获取对象时,你可以将其转换为正确的接口类型,这样你就仍然具有静态绑定,即使创建是晚期绑定。 - zumalifeguard
链接中的文章很棒!非常感谢! - horgh

0

这是解决方案

在.NET中编译版本不可知的DLL

如果该链接失效,关键是像下面这样处理AppDomain.CurrentDomain.AssemblyResolve事件。每次程序集绑定失败时,事件都会触发,因此您可以自己解决它并修复版本冲突。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接