COM-Interop程序集在从Vb调用时未找到本机(.Net)依赖性

时间:2016-10-10 08:10:12

标签: c# json.net dependency-management com-interop

我有一个C#COM-Interop程序集,我从Visual Basic 6应用程序调用。此程序集使HTTP请求发送和检索JSON。

使用C#测试客户端进行测试时,程序集工作正常。

但是,在使用VB6应用程序时,会返回以下错误:

  

“无法加载文件或程序集”Newtonsoft.Json,Version = 4.5.0.0,Culture = neutral,PublicKeyToken = 30ad4fe6b2a6aeed'或其中一个依赖项。系统找不到指定的文件。“

Newtonsoft.Json.dll与COM-Interop DLL(TLB)位于同一文件夹中。

是否需要明确加载Newtonsoft.Json.dll?或者可能放在GAC中?

2 个答案:

答案 0 :(得分:2)

这是标准的DLL Hell问题,它是由使用Regasm.exe的/ codepage选项引起的。或者,更常见的是,项目>属性>构建标签> “注册COM互操作”复选框。两者都做同样的事情,他们将DLL的路径写入注册表。当您忙于开发和测试项目时,它是一个非常好的选择,它可以避免每次进行更改时都必须将DLL重新注册到GAC中。

做的是帮助CLR找到任何依赖项。正常的探测规则仍然有效,它在存储EXE的目录中查找appname.exe.config文件。首先查看GAC,接下来是依赖项的EXE路径。配置仍然受DLL地狱的通常受害者的控制,任何人都必须维护EXE。经常是最终用户。因此,显然,会查看存储[ComVisible] DLL的目录。

这是一种温和的DLL Hell,只是一个普通的文件未发现的事故。比讨厌的那种更温和,找到一个正确名称但错误版本的文件。一般来说,Newtonsoft.Json.dll存在一个很大的问题,大约有35个版本。有这么多版本,它是如此受欢迎的库也会产生另一种肮脏,程序使用另一个也使用DLL的COM服务器。但几乎不可避免地是一个不同的版本。在您宣布项目完成后很久就会发生这种情况。其中一个将失去,50-50赔率是你。最终用户的赔率为100%。

是的,GAC解决了这个问题。每个库都会获得他们要求的版本。理想情况下,Newtonsoft将使用将DLL部署到GAC的安装程序为您解决此问题。但这并不是开源图书馆编写者想要提供的那种承诺。他们希望(并且需要)把它变成你的问题。 Microsoft这样做,但他们也有Windows Update,以确保部署关键的错误和安全修复程序。并且有大量人员致力于确保任何新版本始终向后兼容原始版本,因此版本号不必更改。

请注意,您可以利用Microsoft的承诺。您还可以使用DataContractJsonSerializer和JavascriptSerializer类来完成此任务。作为框架的一部分,他们很少出错。

同时,请注意只是文件未找到的问题。您不必在开发计算机上使用GAC,如果不这样做则更好,将文件复制到正确的位置以保持CLR快乐也同样容易。这是与VB6测试程序相同的目录。并且,如果你想使用VB6调试器,使用VB6的额外怪癖,进入C:\ Program Files(x86)\ Visual Studio \ VB6。部署时请使用GAC。

答案 1 :(得分:2)

Hans为为什么发生这种情况提供了很好的解释。让我提供一个解决方法,使无需在GAC中注册Json DLL或将其复制到VB6 EXE目录。

在COM-visible C#库中,我们可以告诉.NET运行时环境在C#库的目录中搜索Json DLL而不是"通常"路径。我们通过将自己的处理程序附加到AssemblyResolve事件:

来实现
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
{
    // We only want this workaround for one particular DLL
    if (e.Name != "Newtonsoft.Json")
        return null;

    var myLibraryFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var path = Path.Combine(myLibraryFolder, "Newtonsoft.Json.dll");

    return Assembly.LoadFrom(path);
};

有关此解决方法的说明:

  • 此代码仅在执行可能导致抖动加载JSON库的任何内容之前在C#库中执行时才有效。例如,在执行此代码之前,VB6进程中的库或任何其他.NET库都不能调用任何引用JSON库类型的方法。

  • 您可以修改整个过程的行为,而不仅仅是您的库。如果你的VB6进程使用另一个使用JSON的库,你的"重定向"也会影响其他图书馆。