[英]understanding CLR/System.IO.FileNotFoundException "Could not load file or assembly ... or one of its dependencies"
I have an issue with using System.Text.Json
insinde my C# class library, which is a SolidWorks addin.我在我的 C# 类库中使用System.Text.Json
时遇到问题,这是一个 SolidWorks 插件。 It is probably an instance of DLL hell as described here .它可能是此处描述的 DLL 地狱的一个实例。
Since this approach does not work, I might be able to figure something out if I understand a bit more about this issue.由于这种方法不起作用,如果我对这个问题有更多了解,我可能会想出一些办法。 Maybe someone can help?也许有人可以帮忙?
First - my code.首先 - 我的代码。
My 'csproj' file:我的“csproj”文件:
<Project Sdk="Microsoft.NET.Sdk">
<!-- general stuff -->
<PropertyGroup>
<TargetFrameworks>net48</TargetFrameworks>
<ImplicitUsings>disable</ImplicitUsings>
</PropertyGroup>
<!-- references: the top two are SolidWorks API (needed for making a SolidWorks addin -->
<ItemGroup>
<PackageReference Include="com.solidworks.core" Version="29.5.1" />
<PackageReference Include="com.solidworks.tools" Version="21.5.0" />
<PackageReference Include="System.Text.Json" Version="6.0.2" />
</ItemGroup>
<!-- In order to have the addin available within SolidWorks,
it's dll needs to be registered in the codebase. For convenience
we automatically register on build and unregister on clean. -->
<Target Name="Register" AfterTargets="AfterBuild">
<Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe "$(TargetPath)" /codebase" />
</Target>
<Target Name="Unregister" BeforeTargets="BeforeClean">
<Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe "$(TargetPath)" /u" />
</Target>
</Project>
The relevant parts of my cs
file:我的cs
文件的相关部分:
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using SolidWorks...; // all the SolidWorks usings required
namespace SwxAddin
{
[Guid("acb6f17b-9738-4f11-a324-30e05625ff89")]
[ComVisible(true)]
public class SwxAddinImpl : ISwAddin
{
// will be called on addin load in SolidWorks
public bool ConnectToSW(object swx, int addinId)
{
var jsonText = "{ \"foo\": { \"bar\": 2 } }";
var doc = System.Text.Json.JsonDocument.Parse(jsonText); // exception occurs
return swx != null;
}
// will be called on addin unload in SolidWorks
public bool DisconnectFromSW() { return true; }
// This is run when registering the dll. It writes some stuff into the
// SolidWorks registry to make the addin available.
[ComRegisterFunction]
protected static void RegisterFunction(Type type) { ... }
// This is run when unregistering the dll. It removes the stuff from the
// SolidWorks registry that was written into it by RegisterFunction.
[ComUnregisterFunction]
protected static void UnregisterFunction(Type type) { ... }
}
}
When I run SolidWorks after building (and thus, registering my dll in the codebase) and debug it, I get a runtime error on当我在构建后运行 SolidWorks(因此,在代码库中注册我的 dll)并调试它时,我得到一个运行时错误
var doc = System.Text.Json.JsonDocument.Parse(jsonText);
saying说
Exception has occurred: CLR/System.IO.FileNotFoundException An exception of type 'System.IO.FileNotFoundException' occurred in System.Text.Json.dll but was not handled in user code: 'Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.发生异常:CLR/System.IO.FileNotFoundException System.Text.Json.dll 中发生“System.IO.FileNotFoundException”类型的异常,但未在用户代码中处理:“无法加载文件或程序集”System.Runtime .CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 或其依赖项之一。 The system cannot find the file specified.'该系统找不到指定的文件。'
. . As mentioned above, I did try adding如上所述,我确实尝试添加
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
to my csproj file, resulting in the following .dll.config
file in my bin/Debug folder:到我的 csproj 文件,从而在我的 bin/Debug 文件夹中生成以下.dll.config
文件:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
but the runtime error still occurs.但运行时错误仍然发生。
So I'd like to actually understand the issue instead of just following cooking recipes.所以我想真正理解这个问题,而不是仅仅遵循烹饪食谱。 Here are some things I tried and thoughts:以下是我尝试过的一些事情和想法:
System.Text.Json.dll
.该错误表明问题出在System.Text.Json.dll
内部。 I understand it so that the file System.Text.Json.dll
, which lies in location A
, expects a file System.Runtime.CompilerServices.Unsafe.dll
of version 4.0.4.1
in location B
, but in location B
there is a different version of file System.Runtime.CompilerServices.Unsafe.dll
(or no file of that name at all).我理解它,因此位于位置A
的文件System.Text.Json.dll
期望位置B
的版本为4.0.4.1
的文件System.Runtime.CompilerServices.Unsafe.dll
,但在位置B
有一个不同的文件System.Runtime.CompilerServices.Unsafe.dll
的版本(或根本没有该名称的文件)。 => Can anyone tell me which locations A
and B
we are talking about? =>谁能告诉我我们在谈论哪些地点A
和B
? Is it a certain folder?是某个文件夹吗? Is it the GAC?是GAC吗? In case it is the GAC, are we actually talking about files, or something else?如果是 GAC,我们实际上是在谈论文件还是其他什么?
$myProjectPath\bin\Debug\net48
.我检查了(对我来说)最可能的位置,文件夹$myProjectPath\bin\Debug\net48
。 There I can find (amongst others) both dlls System.Text.Json.dll
and System.Runtime.CompilerServices.Unsafe.dll
.在那里我可以找到(除其他外)两个dll System.Text.Json.dll
和System.Runtime.CompilerServices.Unsafe.dll
。 I opened both in some decompilation tool to check their versions and the versions of their references.我在一些反编译工具中打开了它们以检查它们的版本和它们的参考版本。 This is what I found:这是我发现的: System.Text.Json.dll
has version 6.0.0.2
and references System.Runtime.CompilerServices.Unsafe.dll
of version 6.0.0.0
. System.Text.Json.dll
的版本为6.0.0.2
并引用System.Runtime.CompilerServices.Unsafe.dll
的版本6.0.0.0
。
System.Runtime.CompilerServices.Unsafe.dll
has version 6.0.0.0
. System.Runtime.CompilerServices.Unsafe.dll
的版本为6.0.0.0
。
=> So the required version and the present version of System.Runtime.CompilerServices.Unsafe.dll
do align. =>所以所需版本和System.Runtime.CompilerServices.Unsafe.dll
的当前版本确实对齐。 Why do I then get the error?为什么我会收到错误消息? Doesn't this just mean that location A
and B
are NOT $myProjectPath\bin\Debug\net48
?这不只是意味着位置A
和B
不是$myProjectPath\bin\Debug\net48
吗? Or is the referenced version ignored under some circumstances?还是在某些情况下忽略了引用的版本? What kind of cirumstances?什么样的情况?
I built a standalone console app, just using System.Text.Json
and containing the two lines我构建了一个独立的控制台应用程序,仅使用System.Text.Json
并包含两行
var jsonText = "{ \"foo\": { \"bar\": 2 } }";
var doc = System.Text.Json.JsonDocument.Parse(jsonText);
inside it Main
method.在里面Main
方法。 No runtime error occurs there.那里没有发生运行时错误。 So SolidWorks must be the culprit somehow , even if it is not mentioned in the runtime error message.所以 SolidWorks 一定是罪魁祸首,即使它没有在运行时错误消息中提及。
System.Text.Json
version 6.0.0.0
is already loaded (from my $myProjectPath\bin\Debug\net48
folder). System.Text.Json
版本6.0.0.0
已加载(从我的$myProjectPath\bin\Debug\net48
文件夹)。
System.Runtime.CompilerServices.Unsafe
is not loaded. System.Runtime.CompilerServices.Unsafe
未加载。
=> But if System.Runtime.CompilerServices.Unsafe
has not been loaded before, why does System.Text.Json
want to load version 4.0.4.1
instead of the version specified in its own references ( 6.0.0.0
)? =>但是如果之前没有加载过System.Runtime.CompilerServices.Unsafe
,为什么System.Text.Json
要加载版本4.0.4.1
而不是自己引用中指定的版本( 6.0.0.0
)? Where does the 4.0.4.1
come from? 4.0.4.1
是从哪里来的?
Thanks to M Kloster's comment, I could work around the issue by manually loading the assembly - although this unfortunately does not help understanding the issue.感谢 M Kloster 的评论,我可以通过手动加载程序集来解决这个问题——尽管不幸的是这无助于理解这个问题。
First I inserted the line首先我插入了行
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
into the ConnectToSW
method (as first line).进入ConnectToSW
方法(作为第一行)。
Then I implemented MyResolveEventHandler
like so:然后我像这样实现MyResolveEventHandler
:
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
var nameCompilerServicesUnsafe = "System.Runtime.CompilerServices.Unsafe";
if (args.Name == nameCompilerServicesUnsafe + ", Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
{
var assemblyPath = Assembly.GetCallingAssembly().Location;
if (Path.GetFileName(assemblyPath) == "System.Text.Json.dll")
{
var assemblyFolder = Path.GetDirectoryName(assemblyPath);
var pathCompilerServicesUnsafe = Path.Combine(assemblyFolder, nameCompilerServicesUnsafe + ".dll");
if (File.Exists(pathCompilerServicesUnsafe))
return Assembly.LoadFile(pathCompilerServicesUnsafe);
}
}
return null;
}
Now, whenever an assembly cannot be loaded by the automatic mechanism, MyResolveEventHandler
will be called.现在,只要自动机制无法加载程序集,就会调用MyResolveEventHandler
。
Here I just check if it is System.Text.Json.dll
trying to load System.Runtime.CompilerServices.Unsafe
version 4.0.4.1
, and if yes, I return the assembly System.Runtime.CompilerServices.Unsafe.dll
from System.Text.Json.dll
's location folder.在这里我只是检查是否是System.Text.Json.dll
试图加载System.Runtime.CompilerServices.Unsafe
version 4.0.4.1
,如果是,我从System.Text.Json.dll
返回程序集System.Runtime.CompilerServices.Unsafe.dll
System.Text.Json.dll
的位置文件夹。
Strangely, this allowed me to confirm that the System.Text.Json.dll
trying to load System.Runtime.CompilerServices.Unsafe
version 4.0.4.1
really is the one located in my $myProjectPath\bin\Debug\net48
folder.奇怪的是,这让我可以确认尝试加载System.Runtime.CompilerServices.Unsafe
版本4.0.4.1
的System.Text.Json.dll
确实是位于我的$myProjectPath\bin\Debug\net48
文件夹中的那个。 Which makes no sense to me, as the decompilation tool told me that the file $myProjectPath\bin\Debug\net48\System.Text.Json.dll
references System.Runtime.CompilerServices.Unsafe
version 6.0.0.0
, not 4.0.4.1
.这对我来说毫无意义,因为反编译工具告诉我文件$myProjectPath\bin\Debug\net48\System.Text.Json.dll
引用System.Runtime.CompilerServices.Unsafe
version 6.0.0.0
,而不是4.0.4.1
。
And as I said in my question, the issue does not occur outside of SolidWorks (eg in a standalone console app).正如我在问题中所说,该问题不会出现在 SolidWorks 之外(例如,在独立控制台应用程序中)。 So SolidWorks must somehow interfere in the (automatic) assembly resolving mechanism, maybe redirecting bindings?所以 SolidWorks 必须以某种方式干预(自动)装配体解析机制,也许是重定向绑定? Very mysterious... Is there a way to turn that off?很神秘...有没有办法把它关掉?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.