簡體   English   中英

了解 CLR/System.IO.FileNotFoundException “無法加載文件或程序集......或其依賴項之一”

[英]understanding CLR/System.IO.FileNotFoundException "Could not load file or assembly ... or one of its dependencies"

我在我的 C# 類庫中使用System.Text.Json時遇到問題,這是一個 SolidWorks 插件。 它可能是此處描述的 DLL 地獄的一個實例。

由於這種方法不起作用,如果我對這個問題有更多了解,我可能會想出一些辦法。 也許有人可以幫忙?

首先 - 我的代碼。

我的“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 &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文件的相關部分:

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) { ... }
    }
}

當我在構建后運行 SolidWorks(因此,在代碼庫中注冊我的 dll)並調試它時,我得到一個運行時錯誤

var doc = System.Text.Json.JsonDocument.Parse(jsonText);

發生異常:CLR/System.IO.FileNotFoundException System.Text.Json.dll 中發生“System.IO.FileNotFoundException”類型的異常,但未在用戶代碼中處理:“無法加載文件或程序集”System.Runtime .CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 或其依賴項之一。 該系統找不到指定的文件。'

. 如上所述,我確實嘗試添加

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

到我的 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>

但運行時錯誤仍然發生。

所以我想真正理解這個問題,而不是僅僅遵循烹飪食譜。 以下是我嘗試過的一些事情和想法:

  1. 該錯誤表明問題出在System.Text.Json.dll內部。 我理解它,因此位於位置A的文件System.Text.Json.dll期望位置B的版本為4.0.4.1的文件System.Runtime.CompilerServices.Unsafe.dll ,但在位置B有一個不同的文件System.Runtime.CompilerServices.Unsafe.dll的版本(或根本沒有該名稱的文件)。

=>誰能告訴我我們在談論哪些地點AB 是某個文件夾嗎? 是GAC嗎? 如果是 GAC,我們實際上是在談論文件還是其他什么?

  1. 我檢查了(對我來說)最可能的位置,文件夾$myProjectPath\bin\Debug\net48 在那里我可以找到(除其他外)兩個dll System.Text.Json.dllSystem.Runtime.CompilerServices.Unsafe.dll 我在一些反編譯工具中打開了它們以檢查它們的版本和它們的參考版本。 這是我發現的:
  • System.Text.Json.dll的版本為6.0.0.2並引用System.Runtime.CompilerServices.Unsafe.dll的版本6.0.0.0

  • System.Runtime.CompilerServices.Unsafe.dll的版本為6.0.0.0

=>所以所需版本和System.Runtime.CompilerServices.Unsafe.dll的當前版本確實對齊。 為什么我會收到錯誤消息? 這不只是意味着位置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 Studio 中的模塊(調試 -> Windows -> 模塊)。 事實證明,就在錯誤發生之前
  • System.Text.Json版本6.0.0.0已加載(從我的$myProjectPath\bin\Debug\net48文件夾)。

  • System.Runtime.CompilerServices.Unsafe未加載。

=>但是如果之前沒有加載過System.Runtime.CompilerServices.Unsafe為什么System.Text.Json要加載版本4.0.4.1而不是自己引用中指定的版本( 6.0.0.0 )? 4.0.4.1是從哪里來的?

感謝 M Kloster 的評論,我可以通過手動加載程序集來解決這個問題——盡管不幸的是這無助於理解這個問題。

首先我插入了行

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

進入ConnectToSW方法(作為第一行)。

然后我像這樣實現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;
}

現在,只要自動機制無法加載程序集,就會調用MyResolveEventHandler

在這里我只是檢查是否是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的位置文件夾。

奇怪的是,這讓我可以確認嘗試加載System.Runtime.CompilerServices.Unsafe版本4.0.4.1System.Text.Json.dll確實是位於我的$myProjectPath\bin\Debug\net48文件夾中的那個。 這對我來說毫無意義,因為反編譯工具告訴我文件$myProjectPath\bin\Debug\net48\System.Text.Json.dll引用System.Runtime.CompilerServices.Unsafe version 6.0.0.0 ,而不是4.0.4.1

正如我在問題中所說,該問題不會出現在 SolidWorks 之外(例如,在獨立控制台應用程序中)。 所以 SolidWorks 必須以某種方式干預(自動)裝配體解析機制,也許是重定向綁定? 很神秘...有沒有辦法把它關掉?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM