runtime: Dependency manifest (deps.json) has no entry for Private=false reference and additionalProbingPath doesn't work
Hello,
I try to move app from net472 to net5 using Visual Studio 16.8.3 and netcore sdk 5.0.101. App use external libraries/apps (that are build under net472) and reference a couple of them. To avoid a several copy of references (Private=false
) and to separate them from main app in folder them are placed in sub folder and app has a corresponding probing
in the app.config
to correctly load them in runtime.
However, the similar results cannot be obtain in .net5:
Firstly, Private=false
avoid generating an entry in *.deps.json
for this references, that cause an error System.IO.FileNotFoundException: 'Could not load file or assembly... The system cannot find the file specified.
Secondly, (without Private=false
and manually removing this assemblies from the root output folder) netcore runtime doesn’t try to find assemblies in additionalProbingPath
that was listed in runtimeconfig.template.json
, that cause an error An assembly specified in the application dependencies manifest (ConsoleApp.deps.json) was not found
.
The simple project that shows behavior: ConsoleApp.zip
So is it a way to put external libraries in a sub directory without copying them to root folder and resolve them correctly in runtime? Besides, I hope it can be done without append to app dynamically resolving by handling AssemblyLoadContext.Resolving
.
If I miss something, please let me know about it.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 3
- Comments: 19 (14 by maintainers)
@GeorgeAlexandria I’m sorry I missed the part about
additionalProbingPaths
not working in the case where the file is listed in.deps.json
but missing on disk.Additional probing paths
additionalProbingPaths
don’t really work the way you would expect - they’re basically designed for NuGet packages (long history, I don’t like it, but for now we’re stuck with it). For example, let’s say I have a classlib calledLib
, version1.0
and I include it indeps.json
but delete it from the output. And then I haveadditionalProbingPath
set to a directoryC:\probe
.In this case the host will look for file
C:\probe\Lib\1.0\Lib.dll
- because that’s how NuGet packages are placed on disk.So while technically possible to use, I would not recommend using
additionalProbingPaths
because it’s just very cumbersome. There’s also no good way to tell it “subdirectory of the app”. It will let you specify a relative path, but it’s resolved based on the current directory, not the app directory. So it can point to random places depending on how the app is started.Assembly resolution in code
@KylePreuss the reason why it doesn’t work is that you’re using the library from
Main
. The way this works is thatMain
is loaded and JITed - and in order to JIT it, all of the referenced types/assemblies must be resolved BEFORE it gets executed. So the custom resolution logic is not in place when that happens.The way to “Fix” that is to setup the assembly resolution and put everything else into a different method (preferably marked as no-inlining), that way the assembly resolution setup is executed before the code which needs it is JITed.
For example this works:
For the case where you want some dependencies in a subfolder I would go with the code solution. If you own the calling app and the subfolder is fixed (doesn’t change per deployment) the code solution is really no different from config solution - it’s basically just written in different language. It’s also way more flexible and easier to debug 😃.