runtime: MissingMethodException for dynamically loaded Assembly
In my situation I’m trying to compile an application at runtime and loading it into a custom AssemblyContext as suggested by another issue as workaround: https://github.com/dotnet/coreclr/issues/6411
With this workaround in place I noticed another error. The runtime doesn’t seem to load a required System.IO.Compression.ZipFile assembly. Instead it fails when using the ZipArchive extension methods defined in ZipFilExtensions.
I hooked into the AssemblyResolve event and the following is what I’m seeing:
Starting Target: DotnetCoreCreateZipPackages (==> BootstrapAndBuildDnc)
Trying to resolve: System.IO.Compression, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Redirect assembly load to known assembly: System.IO.Compression, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 (Some
"C:\PROJ\FAKE\nuget\dotnetcore\Fake.netcore\current\System.IO.Compression.dll")
Finished Target: DotnetCoreCreateZipPackages
Trying to resolve: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Unable to find assembly {FullName =
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
Version = "4.0.0.0";
Location =
"C:\PROJ\FAKE\.fake\build.fsx\packages\Microsoft.NETCore.Portable.Compatibility\ref\netstandard1.0\System.Core.dll";}. (Error: System.BadImageFormatException: Could not load file or assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL'. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)
File name: 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL' ---> System.BadImageFormatException: Cannot load a reference assembly for execution.
at System.Runtime.Loader.AssemblyLoadContext.LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, String ilPath, String niPath, ObjectHandleOnStack retAssembly)
at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
at Fake.Runtime.CoreCache.realLoadAssembly@205(AssemblyLoadContext loadContext, Boolean printDetails, AssemblyInfo assemInfo)
at Fake.Runtime.CoreCache.loadAssembly(AssemblyLoadContext loadContext, Boolean printDetails, AssemblyInfo assemInfo)) Could not resolve: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Error:
System.MissingMethodException: Method not found: 'System.IO.Compression.ZipArchiveEntry System.IO.Compression.ZipFileExtensions.CreateEntryFromFile(System.IO.Compression.ZipArchive, System.String, System.String)'.
at Fake.IO.Zip.createZipP[a](String fileName, a comment, Int32 level, IEnumerable`1 items)
at Fake.IO.Zip.CreateZip[a](String workingDir, String fileName, a comment, Int32 level, Boolean flatten, IEnumerable`1 files)
at FSI_0002.clo@587-37.Invoke(Unit _arg2)
at Fake.Core.Targets.runSingleTarget(TargetTemplate`1 target)
So it is not even trying to load the required assembly. Interestingly when I add
let lc = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(typeof<MyClass>.GetTypeInfo().Assembly)
let n = AssemblyName "System.IO.Compression.ZipFile"
lc.LoadFromAssemblyName(n) |> ignore
just before using the failing method everything works as it should…
You can reproduce this by typing the following into a git bash (windows 10 x64):
git clone git@github.com:matthid/FAKE.git
export APPDATA=$HOME LocalAppData=$HOME # Only when on unix
cd FAKE
git checkout 8a59f34
SkipTests=true NO_DOTNETCORE_BOOTSTRAP=true ./build.sh # Builds all the stuff we need, will take a while
rm nuget/dotnetcore/Fake.netcore/fake-dotnetcore*.zip
COREHOST_TRACE=1 ./nuget/dotnetcore/Fake.netcore/current/Fake.netcore.exe -v run build.fsx -t DotnetCoreCreateZipPackages --singletarget # NOTE Works first time
rm nuget/dotnetcore/Fake.netcore/fake-dotnetcore*.zip
COREHOST_TRACE=1 ./nuget/dotnetcore/Fake.netcore/current/Fake.netcore.exe -v run build.fsx -t DotnetCoreCreateZipPackages --singletarget # Now fails every run, I think in the uncached run the required assembly is loaded in another path
To add the workaround
git merge 80c3d2d
rm -rf .fake/build.fsx # just to be save 2nd time
rm -rf ~/.nuget/packages/Fake.* # when running second time, just to be safe
SkipTests=true NO_DOTNETCORE_BOOTSTRAP=true ./build.sh # Builds all the stuff we need, will take a while
rm nuget/dotnetcore/Fake.netcore/fake-dotnetcore*.zip
COREHOST_TRACE=1 ./nuget/dotnetcore/Fake.netcore/current/Fake.netcore.exe -v run build.fsx -t DotnetCoreCreateZipPackages --singletarget # NOTE Works first time
rm nuget/dotnetcore/Fake.netcore/fake-dotnetcore*.zip
COREHOST_TRACE=1 ./nuget/dotnetcore/Fake.netcore/current/Fake.netcore.exe -v run build.fsx -t DotnetCoreCreateZipPackages --singletarget # NOTE Works second time
This uses the latest RTM packages of the dotnetcore runtime. I couldn’t reproduce this on a smaller sample but I tried to make it as easy as possible to reproduce.
I noticed that AssemblyResolve is not triggered for ZipFile in the first (working) run either. Any help is welcome. Maybe related https://github.com/dotnet/corefx/issues/10787
Please ask if you have further questions about this setup.
TLDR: Runtime is throwing MissingMethodException without even trying to load the required assembly. When loading the assembly by hand it works.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 15 (7 by maintainers)
Commits related to this issue
- workaround https://github.com/dotnet/coreclr/issues/7043 — committed to matthid/FAKE by matthid 7 years ago
Yes, since attempt to get a Type may require creating the type and thus, loading the assembly in which the type is defined (and any other assemblies defining the types that are dependencies of the type being created).