首页 > 解决方案 > 将 .net Framework 项目与 .net Core 项目(和语言)混合 - System.IO.FileNotFoundException

问题描述

我有一个解决方案,其中大多数项目都是针对 .NET Framework 4.8 的 VB.net 项目。所有这些特定项目都可以正确编译并在生产中运行。

我添加了一个针对 .net 标准 2.0 的 C# 项目。这个特定项目的主要原因是创建一个可以处理剃刀模板的组件(当然给定一个模型),以便使用 RazorLight_wik8wz nuget 包创建输出文件(我并不关心我使用哪个包,只要我可以在内存中渲染一个剃刀模板,因为模型/模板对生成的输出在不同情况下可能会保存在不同的地方)。

理论上,根据我的理解,我应该能够从我的其他 .net 框架 4.8 项目中引用和使用 .net 标准 2.0 库项目。但是,我似乎无法让它工作(即使一切都编译并运行)。

我已经尝试了几个基于 RazorLight 的不同软件包——但是当我尝试使用它们时,我得到了类似的结果。我只是不确定我是否遇到了错误或者我没有正确地做某事。

C# 项目名为“JobOutputGenerator”。我添加了名为“RazorLight_wik8wz”的 nuget 包,并创建了一个名为 JobOutput 的对象,该对象当前如下所示:

using System.Threading.Tasks;
using RazorLight;

public class JobOutput
{
    public static async Task<byte[]> CreateOutputAsync(string RazorTemplate, object Model)
    {
        RazorLightEngine engine = new RazorLightEngineBuilder().UseMemoryCachingProvider().Build();
        return System.Text.Encoding.ASCII.GetBytes(await engine.CompileRenderAsync(RazorTemplate.GetHashCode().ToString() + Model.GetHashCode().ToString(), RazorTemplate, Model));
    }

}

我创建了另一个名为“TesterApp”的项目,它是一个针对 .NET Framework 4.8 的 VB.NET 项目。这是一个引用 JobOutputGenerator 的简单 Windows 窗体项目。

我有一个执行以下操作的按钮:

Private Sub btnRenderSample_Click(sender As Object, e As EventArgs) Handles btnRenderSample.Click
    Dim template As String = "Hello @Model.Name"
    Dim Model1 = New With {.Name = "John Doe"}
    Dim bytesTask = JobOutput.CreateOutputAsync(template, Model1)
    Dim str = System.Text.Encoding.ASCII.GetString(bytesTask.Result)
    MsgBox(str)
End Sub

当我在 Visual Studio 中以调试模式启动 TesterApp 时,所有项目都编译得很好,然后当我单击我的示例按钮时,Visual Studio 中断行(以绿色突出显示):

Dim bytesTask = JobOutput.CreateOutputAsync(template, Model1)

带有一个标题为“异常未处理”的框,上面写着:

System.IO.FileNotFoundException:'无法加载文件或程序集'RazorLight,版本 = 2.0.0.0,文化 = 中性,PublicKeyToken = null'或其依赖项之一。该系统找不到指定的文件。'

我已经运行了 fuslogvw 并且 TesterApp 定位 JobOutputGenerator.dll 没有问题:

<meta http-equiv="Content-Type" content="charset=unicode-1-1-utf-8"><!-- saved from url=(0015)assemblybinder: --><html><pre>
*** Assembly Binder Log Entry  (6/7/2019 @ 9:37:08 AM) ***

The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = JobOutputGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = TesterApp.exe
Calling assembly : TesterApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/JobOutputGenerator.DLL.
LOG: Assembly download was successful. Attempting setup of file: X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\JobOutputGenerator.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: JobOutputGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Binding succeeds. Returns assembly from X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\JobOutputGenerator.dll.
LOG: Assembly is loaded in default load context.

</pre></html>

但是,我确实在 fuslogvw 中找到了这个小“宝石”,但我不知道该怎么办:

*** Assembly Binder Log Entry  (6/7/2019 @ 9:37:09 AM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = RazorLight, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = TesterApp.exe
Calling assembly : JobOutputGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight.DLL.
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight/RazorLight.DLL.
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight.EXE.
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight/RazorLight.EXE.
LOG: All probing URLs attempted and failed.

以下是 JobOutputGenerator.csproj 的内容:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup Label="Globals">
    <SccProjectName>SAK</SccProjectName>
    <SccProvider>SAK</SccProvider>
    <SccAuxPath>SAK</SccAuxPath>
    <SccLocalPath>SAK</SccLocalPath>
  </PropertyGroup>

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <PropertyGroup>
    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  </PropertyGroup>


  <ItemGroup>
    <PackageReference Include="ILRepack.MSBuild.Task" Version="2.0.1" />
    <PackageReference Include="RazorLight_wik8wz" Version="2.0.0" />
  </ItemGroup>

      <Target Name="ILRepack" AfterTargets="Build">

        <PropertyGroup>
            <WorkingDirectory>$(MSBuildThisFileDirectory)bin\$(Configuration)\$(TargetFramework)</WorkingDirectory>
        </PropertyGroup>

        <ILRepack 
            OutputType="$(OutputType)" 
            MainAssembly="$(AssemblyName).dll" 
            OutputAssembly="$(AssemblyName).dll" 
            InputAssemblies="$(WorkingDirectory)\*.dll" 
            WilcardInputAssemblies="true"
            WorkingDirectory="$(WorkingDirectory)" />
    </Target>
</Project>

标签: c#vb.net.net-standard-2.0.net-core-2.2.net-4.7.1

解决方案


因此,经过更多搜索后,我遇到了以下问题和一组帖子。遵循此解决方法似乎暂时解决了我的问题。

显然,这在很长一段时间内一直是个问题(自 2017 年以来——感谢微软!),没有永久修复。

该问题首先在这里报告:

从经典 .NET 应用程序引用的 .NET Standard 库的 NuGet 依赖项无法在运行时解析 FileNotFoundException #1582

如果您通读这串消息,您最终会 在底部附近找到此解决方法,其他人会确认此人的发现。遵循此解决方法会导致 DLL 文件全部构建/复制到 Debug 文件夹,现在引用的 DLL 不再“丢失”,并且我在运行时收到的异常消失了。

我对我的 JobOutputGenerator .csproj 文件进行了修改,除了我使用 ;net48 而不是 ;net461 。

注意标签:

<TargetFramework>

需要更改为(注意“s”)

<TargetFrameworks>

为了使它工作 - 否则您的项目将无法在 Visual Studio 中正确加载。


推荐阅读