首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解CLR/System.IO.FileNotFoundException“无法加载文件或程序集.或其依赖项之一”

理解CLR/System.IO.FileNotFoundException“无法加载文件或程序集.或其依赖项之一”
EN

Stack Overflow用户
提问于 2022-07-14 10:23:23
回答 1查看 235关注 0票数 0

我在使用System.Text.Json暗示我的C#类库时遇到了问题,它是一个SolidWorks加载项。正如描述的这里那样,它可能是DLL地狱的一个实例。

由于这种方法不起作用,如果我对这个问题有更多的了解,我可能会想出一些办法。也许有人能帮忙?

首先-我的密码。

我的“csproj”文件:

代码语言:javascript
运行
复制
<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 &quot;$(TargetPath)&quot; /codebase" />
  </Target>
  <Target Name="Unregister" BeforeTargets="BeforeClean">
    <Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe &quot;$(TargetPath)&quot; /u" />
  </Target>

</Project>

我的cs文件的相关部分:

代码语言:javascript
运行
复制
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) { ... }
    }
}

当我在构建(从而在代码库中注册我的dll )并调试它之后运行SolidWorks时,我会在

代码语言:javascript
运行
复制
var doc = System.Text.Json.JsonDocument.Parse(jsonText);

已发生异常: CLR/System.IO.FileNotFoundException --“System.IO.FileNotFoundException”类型的异常发生在System.Text.Json.dll中,但未在用户代码中处理:“无法加载文件或程序集'System.Runtime.CompilerServices.Unsafe、Version=4.0.4.1、Culture=neutral、PublicKeyToken=b03f5f7f11d50a3a‘或其依赖项之一。系统找不到指定的文件。

。如前所述,我确实尝试过添加

代码语言:javascript
运行
复制
<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

到我的csproj文件,从而在bin/Debug文件夹中生成以下.dll.config文件:

代码语言:javascript
运行
复制
<?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>

但是运行时错误仍然发生。

因此,我想真正理解这个问题,而不只是遵循烹饪食谱。以下是我尝试过的一些事情和一些想法:

  1. 错误说问题在System.Text.Json.dll内部。我理解它是因为位于location A中的文件A期望在location B中有版本4.0.4.1的文件System.Runtime.CompilerServices.Unsafe.dll,但是在location B中有不同版本的文件System.Runtime.CompilerServices.Unsafe.dll (或者根本没有这个名称的文件)。

有谁能告诉我我们所说的A B 的位置?是一个特定的文件夹吗?是GAC吗?如果是GAC,我们实际上是在谈论文件还是别的什么?

  1. 我检查了(对我来说)最可能的位置,文件夹$myProjectPath\bin\Debug\net48。在那里,我可以找到(除其他外)dll、System.Text.Json.dllSystem.Runtime.CompilerServices.Unsafe.dll。我打开了一些反编译工具来检查它们的版本和引用的版本。这就是我发现的:
  • System.Text.Json.dll具有版本6.0.0.2和references System.Runtime.CompilerServices.Unsafe.dll of version 6.0.0.0
  • System.Runtime.CompilerServices.Unsafe.dll6.0.0.0版本。

因此,所需的版本和当前版本的System.Runtime.CompilerServices.Unsafe.dll => 是对齐的。为什么要得到错误呢?这不只是意味着location AB不是$myProjectPath\bin\Debug\net48还是在某些情况下被忽略了引用的版本?什么样的情况?

  1. 我构建了一个独立的控制台应用程序,只使用System.Text.Json并包含这两行 var jsonText = "{ \"foo\": { \"bar\": 2 } }"; var doc = System.Text.Json.JsonDocument.Parse(jsonText);

在它的内部Main方法。那里没有出现运行时错误。所以SolidWorks必须是罪魁祸首,即使在运行时错误消息中没有提到它。

  1. 这篇文章涵盖dll地狱,并给出了故障排除的建议。我检查了Visual中的模块(调试-> Windows ->模块)。结果是在错误发生之前
  • System.Text.Json版本6.0.0.0已经加载(从我的$myProjectPath\bin\Debug\net48文件夹)。
  • System.Runtime.CompilerServices.Unsafe未加载。

但是,如果System.Runtime.CompilerServices.Unsafe 4.0.4.1 以前没有加载过,那么为什么要加载版本4.0.4.1而不是它自己的引用(6.0.0.0)中指定的版本?E 1111来自哪里?E 2112

EN

回答 1

Stack Overflow用户

发布于 2022-07-14 12:05:02

感谢M的评论,我可以通过手动加载程序集来解决这个问题--尽管这无助于理解这个问题。

首先我插入了行

代码语言:javascript
运行
复制
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

进入ConnectToSW方法(作为第一行)。

然后,我实现了这样的MyResolveEventHandler

代码语言:javascript
运行
复制
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;
}

现在,当程序集无法通过自动机制加载时,将调用MyResolveEventHandler

在这里,我只检查是否System.Text.Json.dll试图加载System.Runtime.CompilerServices.Unsafe版本4.0.4.1,如果是,则从System.Text.Json.dll的location文件夹返回程序集System.Runtime.CompilerServices.Unsafe.dll

奇怪的是,这使我能够确认试图加载System.Runtime.CompilerServices.Unsafe版本4.0.4.1System.Runtime.CompilerServices.Unsafe确实是位于我的$myProjectPath\bin\Debug\net48文件夹中。这对我来说毫无意义,因为反编译工具告诉我,文件$myProjectPath\bin\Debug\net48\System.Text.Json.dll引用的是System.Runtime.CompilerServices.Unsafe版本的6.0.0.0,而不是4.0.4.1

正如我在问题中所说的,这个问题并不发生在SolidWorks之外(例如,在一个独立的控制台应用程序中)。因此,SolidWorks必须以某种方式干预(自动)组装解析机制,可能会重定向绑定吗?非常神秘..。有办法把它关掉吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72978989

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档