sdk: Cli tool throws exception when dispatching and calling into "PlatformAbstractions" APIs
Steps to reproduce
Repro repo here.
I have a tool that needs to load the target project, which targets the full .Net framework. As a result, I should dispatch the execution to the context of the target tfm (so net46 for example), because cli tools are always executed in the context of “netcoreapp”. Dispatching like this used to work perfectly in the preview2 tooling.
After the dispatch, if I try to use any of the “PlatformAbstractions” APIs the following exception occurs:
Unhandled Exception: System.IO.FileLoadException:
Could not load file or assembly 'Microsoft.DotNet.PlatformAbstractions, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
This line works when the context is “netcoreapp”, but it throws the exception after the dispatch to “net46”.
This is a major problem because “Command.CreateDotNet” fails as a result. My tool has a reference to “Microsoft.DotNet.Cli.Utils” v1.0.1 which I suspect is the root of the problem. Or maybe this is not how dispatching should be done in 1.0? (which I doubt, because when PlatformAbstractions is not involved, everything works).
I can’t find info or documentation at all about this. What’s going on?
Environment data
dotnet --info output:
.NET Command Line Tools (1.0.0)
Product Information:
Version: 1.0.0
Commit SHA-1 hash: e53429feb4
Runtime Environment:
OS Name: Windows
OS Version: 10.0.14393
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\1.0.0
For reference this is the tool I maintain.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 22 (8 by maintainers)
According to NuGet and project.assets.json the lowest version is indeed 1.0.3, but after building the project there’s definitely a reference to 1.0.1 (InformationVersion 1.0.1-beta). Same for Microsoft.Extensions.DependencyModel.
Here’s a minimum .csproj to reproduce: Just run
dotnet restore && dotnet buildIt also reproduces with netcoreapp1.0, but it’s easier to see the output with net462.
Update: Did some more testing and
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="1.0.3" />downloads the 1.0.1.0 (1.0.1-beta) package. Same forMicrosoft.Extensions.DependencyModelJust wrote a prototype and it indeed does not work yet. The project were I include a tool that only targets
net46throws aNU1202error during package restore:Package tool-x 1.0.0 is not compatible with netcoreapp2.0.I just found a newer version of
DotnetToolDispatcherhere: https://github.com/aspnet/Scaffolding/blob/8675aa97cd967d92bfa98e4008feb98853ca25e6/src/Shared/DotNetDispatcher/DotnetToolDispatcher.cs Note the methodEnsureBindingRedirects. I’m slightly optimistic they fixed the binding redirect issue.@livarcocc : Is there an official way to get to work what @mrahhal described (a cli tool that targets netfull)? Or at least an official NuGet package with
DotnetToolDispatcher? Because currently the source is copied over manually an part of the tool project, which seems error prone.@nphmuller I’ll try to dig out the original conv where this whole thing started, way back when I was starting out with Migrator.EF6. But anyway, at that time, docs were very scarce on how to build a tool and I only had a couple of aspnet tools to investigate. But this was problematic because most of them didn’t need to work under the full .net framework.
In my case, you know how we use EntityFramework6, which targets the full .net framework. So in order to use it, the tool must be running under full .net. Unfortunately, and as I’ve learned, dotnet tools are always launched in the context of netcoreapp.
So at the time, I asked a cli tooling dev and he guided me to the process known as dispatching. And that’s really why I do another dispatch after the original execution. (1st execution is under netcoreapp, and here I do dispatching to re-execute the tool under full .net to be able to call EF6)
Right now, I’m not entirely sure if any tool that the aspnetcore team builds needs dispatching. I think they all target netcoreapp. That’s why I wasn’t able to confirm if what I’m doing is 100% compatible with how tooling works, but at least it worked, kinda 😅
But as a conclusion, it’s important to stress that this problem occurs precisely because of the need to dispatch. Sorry if I didn’t make this clear earlier. (As you can see from my old repro that I mentioned in this issue’s description, it has dispatching.)
An excerpt from this issue’s description:
(And thanks @nphmuller for the investigation!)
I always thought we ran in an edge case were we tried to run a DotNetCliToolReference on .NET full. The
runetimeconfig.jsonfile makes sure the binding redirects are right, but it’s only included for anetcoreapptarget. This means that if the target of the project were the CliTool is referenced in is .NET full (likenet462), there’s is no binding redirect file for the tool, hence theFileNotFoundException.I think that is the underlying issue.
My workaround basically makes sure the binding redirect file of the main app is copied for the tool. See: https://github.com/mrahhal/Migrator.EF6/issues/37#issuecomment-288032738
Anyway, yeah I’ve had
FileNotFoundexceptions because of missing binding redirects in ASP.NET Core 2.0 and dotnet cli 2.0 with anet462target. So not with anetcoreapptarget. Not sure if it wasPlatformAbstractionsor another .NET base library. If you’re interested in if it’s specificallyPlatformAbstractions, tell me and I’ll retest it. But for now, I don’t think it matters.