将 .net Framework 项目与 .net Core 项目(和语言)混合 - System.IO.FileNotFoundException
Mixing .net Framework projects with .net Core projects (and languages) - System.IO.FileNotFoundException
我有一个解决方案,其中大部分项目都是 VB.net 项目,它们都以 .NET Framework 4.8 为目标。所有这些特定项目都可以正确编译,并且 运行 正在生产中。
我添加了一个面向 .net 标准 2.0 的 C# 项目。这个特定项目的主要原因是创建一个可以处理剃刀模板的组件(当然给定一个模型)以便使用 RazorLight_wik8wz nuget 包创建输出文件(我真的不在乎我使用哪个包只要我可以在内存中渲染一个剃刀模板,因为 model/template 对生成的输出可能会在不同情况下保存在不同的地方。
理论上,根据我的理解,我应该能够从我的其他 .net Framework 4.8 项目中引用和使用 .net standard 2.0 库项目。但是,我似乎无法让它工作(即使一切都编译并且 运行s)。
我已经尝试了几个基于 RazorLight 的不同包——但是当我尝试使用它们时我得到了相似的结果。我只是不确定我是否遇到了错误,或者我是否没有正确地做某事。
C# 项目名为 "JobOutputGenerator." 我已经添加了名为 "RazorLight_wik8wz" 的 nuget 包并创建了一个名为 object 的 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)
带有一个标题为 "Exception Unhandled" 的框,上面写着:
System.IO.FileNotFoundException: 'Could not load file or assembly 'RazorLight, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.'
我有 运行 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 中找到了这个 "gem",但我不知道该怎么办:
*** 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>
所以经过更多的搜索,我遇到了以下问题和一组帖子。遵循此解决方法似乎暂时解决了我的问题。
显然,这个问题已经存在很长一段时间了(自 2017 年以来——感谢 Microsoft!),没有永久修复。
问题首先报告于此:
如果你通读这串信息,你最终会得到这个
workaround 靠近底部,其他人证实了此人的发现。遵循此解决方法会导致 DLL 文件全部 built/copied 到 Debug 文件夹,现在引用的 DLL 不再 "missing" 并且我在运行时收到的异常消失了。
我对我的 JobOutputGenerator .csproj 文件进行了 this 修改,只是我使用了 ;net48 而不是 ;net461 。
注意标签:
<TargetFramework>
需要改为(注意"s")
<TargetFrameworks>
为了使其正常工作——否则您的项目将无法在 Visual Studio 中正确加载。
我有一个解决方案,其中大部分项目都是 VB.net 项目,它们都以 .NET Framework 4.8 为目标。所有这些特定项目都可以正确编译,并且 运行 正在生产中。
我添加了一个面向 .net 标准 2.0 的 C# 项目。这个特定项目的主要原因是创建一个可以处理剃刀模板的组件(当然给定一个模型)以便使用 RazorLight_wik8wz nuget 包创建输出文件(我真的不在乎我使用哪个包只要我可以在内存中渲染一个剃刀模板,因为 model/template 对生成的输出可能会在不同情况下保存在不同的地方。
理论上,根据我的理解,我应该能够从我的其他 .net Framework 4.8 项目中引用和使用 .net standard 2.0 库项目。但是,我似乎无法让它工作(即使一切都编译并且 运行s)。
我已经尝试了几个基于 RazorLight 的不同包——但是当我尝试使用它们时我得到了相似的结果。我只是不确定我是否遇到了错误,或者我是否没有正确地做某事。
C# 项目名为 "JobOutputGenerator." 我已经添加了名为 "RazorLight_wik8wz" 的 nuget 包并创建了一个名为 object 的 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)
带有一个标题为 "Exception Unhandled" 的框,上面写着:
System.IO.FileNotFoundException: 'Could not load file or assembly 'RazorLight, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.'
我有 运行 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 中找到了这个 "gem",但我不知道该怎么办:
*** 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>
所以经过更多的搜索,我遇到了以下问题和一组帖子。遵循此解决方法似乎暂时解决了我的问题。
显然,这个问题已经存在很长一段时间了(自 2017 年以来——感谢 Microsoft!),没有永久修复。
问题首先报告于此:
如果你通读这串信息,你最终会得到这个 workaround 靠近底部,其他人证实了此人的发现。遵循此解决方法会导致 DLL 文件全部 built/copied 到 Debug 文件夹,现在引用的 DLL 不再 "missing" 并且我在运行时收到的异常消失了。
我对我的 JobOutputGenerator .csproj 文件进行了 this 修改,只是我使用了 ;net48 而不是 ;net461 。
注意标签:
<TargetFramework>
需要改为(注意"s")
<TargetFrameworks>
为了使其正常工作——否则您的项目将无法在 Visual Studio 中正确加载。