简体   繁体   English

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

[英]COM-Interop assembly not finding a native (.Net) dependancy when called from Vb

I have a C# COM-Interop assembly which I am calling from a Visual Basic 6 application. 我有一个C#COM-Interop程序集,我从Visual Basic 6应用程序调用。 This assembly makes HTTP requests to send and retrieve JSON. 此程序集使HTTP请求发送和检索JSON。

The assembly works fine when being testing with a C# test client. 使用C#测试客户端进行测试时,程序集工作正常。

However, when using it from with the VB6 app, the following error is returned: 但是,在使用VB6应用程序时,会返回以下错误:

"Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified." “无法加载文件或程序集'Newtonsoft.Json,Version = 4.5.0.0,Culture = neutral,PublicKeyToken = 30ad4fe6b2a6aeed'或其中一个依赖项。系统找不到指定的文件。”

The Newtonsoft.Json.dll is located within the same folder as the COM-Interop DLL (TLB). Newtonsoft.Json.dll与COM-Interop DLL(TLB)位于同一文件夹中。

Does the Newtonsoft.Json.dll need to be explicitly loaded? 是否需要显式加载Newtonsoft.Json.dll Or maybe placed in the GAC? 或者可能放在GAC中?

This is a standard DLL Hell problem, it is caused by using the /codepage option for Regasm.exe. 这是一个标准的DLL Hell问题,它是由使用Regasm.exe的/ codepage选项引起的。 Or, more commonly, the Project > Properties > Build tab > "Register for COM interop" checkbox. 或者,更常见的是,项目>属性>构建选项卡>“注册COM互操作”复选框。 Both do the same thing, they write the path to the DLL into the registry. 两者都做同样的事情,他们将DLL的路径写入注册表。 It is a very good option to use when you are busy developing and testing the project, it avoids having to re-register the DLL into the GAC every single time you make a change. 当您忙于开发和测试项目时,这是一个非常好的选择,它避免了每次进行更改时都必须将DLL重新注册到GAC中。

But what it does not do is help the CLR find any dependencies. 但它没有做的是帮助CLR找到任何依赖。 The normal probing rules remain in effect, it looks for an appname.exe.config file in the directory where the EXE is stored. 正常的探测规则仍然有效,它在存储EXE的目录中查找appname.exe.config文件。 And first looks in the GAC, next in the EXE path for dependencies. 首先查看GAC,接下来是依赖项的EXE路径。 Configuration remains under control of the usual victim of DLL Hell, whomever has to maintain the EXE. 配置仍然受DLL地狱的通常受害者的控制,任何人都必须维护EXE。 Frequently the end-user. 经常是最终用户。 So, explicitly, it does not look in the directory where your [ComVisible] DLL is stored. 因此,明确的,它看在你的[标记有ComVisible特性] DLL保存的目录。

It is the mild kind of DLL Hell, just a plain file-not-found mishap. 它是一种温和的DLL Hell,只是一个普通的文件未发现的事故。 Much milder than the nasty kind, finding a file with the right name but the wrong version. 比讨厌的那种更温和,找到一个正确名称但错误版本的文件。 In general a strong problem with Newtonsoft.Json.dll, there are about 35 versions in the wild. 一般来说,Newtonsoft.Json.dll存在一个很大的问题,大约有35个版本。 Having so many versions and it being such a popular library also begets the other kind of nastiness, the program using another COM server that also uses the DLL. 有这么多版本,它是如此受欢迎的库也会产生另一种肮脏,程序使用另一个也使用DLL的COM服务器。 But almost inevitably a different version. 但几乎不可避免地是一个不同的版本。 Tends to happen long after you declared your project finished. 在您宣布项目完成后很久就会发生这种情况。 One of them is going to lose, 50-50 odds that it is you. 其中一个将失去,50-50赔率是你。 100% odds for the end-user. 最终用户的赔率为100%。

Yes, the GAC solves this problem. 是的,GAC解决了这个问题。 Each library gets the version they ask for. 每个库都会获得他们要求的版本。 Ideally Newtonsoft would solve this problem for you with an installer that deploys the DLL into the GAC. 理想情况下,Newtonsoft将使用将DLL部署到GAC的安装程序为您解决此问题。 But it is not the kind of commitment that open source library writers ever want to provide. 但这并不是开源图书馆编写者想要提供的那种承诺。 They want (and need) to make it your problem. 他们希望(并且需要)把它变成你的问题。 Microsoft does this, but they also have Windows Update to ensure that critical bug and security fixes get deployed. Microsoft这样做,但他们也有Windows Update,以确保部署关键的错误和安全修复程序。 And have a large number of people working on making sure that any new revisions are always backwards compatible with the original release so the version number doesn't have to change. 并且有大量人员致力于确保任何新版本始终向后兼容原始版本,因此版本号不必更改。

Do note that you can take advantage of Microsoft's commitment. 请注意,您可以利用Microsoft的承诺。 You can also use the DataContractJsonSerializer and JavascriptSerializer classes to get this job done. 您还可以使用DataContractJsonSerializer和JavascriptSerializer类来完成此任务。 Part of the framework, they rarely get it wrong. 作为框架的一部分,他们很少弄错。

Meanwhile, do keep mind that is just a file-not-found problem. 同时,请记住这只是一个文件未找到的问题。 You don't have to use the GAC on your dev machine, and it is better if you don't, it is just as easy to copy the file into the right place to keep the CLR happy. 您不必在开发计算机上使用GAC,如果不这样做则更好,将文件复制到正确的位置以保持CLR快乐也同样容易。 Which is the same directory as your VB6 test program. 这是与VB6测试程序相同的目录。 And, extra quirk with VB6, into C:\\Program Files (x86)\\Visual Studio\\VB6 if you want to use the VB6 debugger. 并且,如果你想使用VB6调试器,使用VB6的额外怪癖,进入C:\\ Program Files(x86)\\ Visual Studio \\ VB6。 Do use the GAC when you deploy. 部署时请使用GAC。

Hans provided a great explanation for why this happens. 汉斯为这种情况发生了原因 Let me offer a workaround for making this work without having to register the Json DLL in the GAC or copying it to the VB6 EXE directory. 让我提供一个解决方法来完成这项工作, 无需在GAC中注册Json DLL或将其复制到VB6 EXE目录。

In your COM-visible C# library, we can tell the .NET runtime environment to search for the Json DLL in the directory of the C# library instead of the "usual" paths. 在COM-visible C#库中,我们可以告诉.NET运行时环境在C#库的目录中搜索Json DLL而不是“通常”路径。 We do that by attaching our own handler to the AssemblyResolve event: 我们通过将自己的处理程序附加到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);
};

Notes about this workaround: 有关此变通方法的说明:

  • This code only works if it is executed in your C# library before doing anything that might cause the jitter to load the JSON library . 此代码仅在执行可能导致抖动加载JSON库的任何操作之前在 C#库中执行时才有效。 For example, neither your library nor any other .NET library in your VB6 process must call any method referencing types from the JSON library before this code is executed. 例如,在执行此代码之前,VB6进程中的库或任何其他.NET库都不能调用任何引用JSON库类型的方法。

  • You modify the the behaviour of the whole process, not just your library. 您可以修改整个过程的行为,而不仅仅是库。 If your VB6 process uses another library using JSON, your "redirect" affects the other library as well. 如果您的VB6进程使用另一个使用JSON的库,那么您的“重定向”也会影响另一个库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 VB6数组语法中的双括号(从.Net com-interop传递) - Double parentheses in VB6 Array syntax (passed from .Net com-interop) 如果在 vs 中构建的项目属性下设置了 com-interop,则无法注册用于 db 迁移的 .Net 程序集 - .Net assembly for db migration can't be registered if com-interop is set under project properties build in vs 托管时 ASP.Net Com-InterOp Excel 生成问题 - ASP.Net Com-InterOp Excel Generation issue when hosting COM-Interop:将.NET Framework版本从2.0更改为4.0 - 我是否也应该更改Guids? - COM-Interop: Change .NET Framework Version from 2.0 to 4.0 - Should I change the Guids also? Get, “cannot cast 'Field' to 'Field' type (same class)” when trying to Append an object in vb6 from C# library using COM-interop - Get, “cannot cast 'Field' to 'Field' type (same class)” when trying to Append an object in vb6 from C# library using COM-interop 如何将暴露给COM-interop的.NET对象标记为单线程? - How to mark .NET objects exposed to COM-interop as single threaded? 为VB6应用要使用的.NET程序集编写COM Interop程序集 - Writing a COM Interop Assembly for a .NET assembly to be consumed by a VB6 app COM-Interop中的十进制封送处理 - Decimal marshaling in COM-Interop 使用Silverlight和com-interop进行打印 - Printing with Silverlight and com-interop 使用COM-Interop将数组从JS返回到C# - Returning an array from JS to C# with COM-Interop
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM