Closed Malcolmnixon closed 1 year ago
Modern versions of MSBuild such as 15.1.0.0 which ship with Visual Studio 17.7.2 are still using .NET Framework 4.7.2; however they have added additional libraries such as Microsoft.IO.Redist
to provide modern methods to older code bases.
In this instance the Microsoft.Build.dll (15.1.0.0)
has a reference to Microsoft.IO.Redist.dll (6.0.0.0)
and makes use of ReadOnlySpan<char> Microsoft.IO.Path.GetFileName(ReadOnlySpan<char> path)
.
When nuget update <solution>
executes, MSBuildUser::LoadAssemblies executes Assembly.Load() on the Microsoft.Build.dll (15.1.0.0)
, which works, but does not load the referenced Microsoft.IO.Redist.dll (6.0.0.0)
assembly. Then in MSBuildProjectSystem::GetProject() it tries to create an instance of the Microsoft.Build.Evaluation.Project
from the Microsoft.Build.dll (15.1.0.0)
, however due to the failure to load the referenced assemblies it gets the following exception:
System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, Object[] args)
at NuGet.Common.MSBuildProjectSystem.GetProject(String projectFile) in NuGet.Client\src\NuGet.Clients\NuGet.CommandLine\Common\MSBuildProjectSystem.cs:line 448
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
MissingMethodException: Method not found: 'System.ReadOnlySpan`1<Char> Microsoft.IO.Path.GetFileName(System.ReadOnlySpan`1<Char>)'.
The problem appears to be not loading referenced assemblies, however https://github.com/NuGet/NuGet.Client/pull/4975 was supposed to fix this problem. It may be the nuget update
path does not correctly hook the AppDomain.CurrentDomain.AssemblyResolve
events and handle them appropriately.
@Malcolmnixon firstly, thank you for creating a sample project/solution and attaching it. Surprisingly few customers reporting problems provide us with a repro to run locally.
Unfortunately, I'm not able to reproduce the error. I was sure to try to test the most similar setup as you, VS 17.7 and nuget.exe 6.6.1. However, it works for me:
MSBuild auto-detection: using msbuild version '17.7.2.37605' from 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64'.
Scanning for projects...
Found 1 project with a packages.config file. (test)
Feeds used:
https://api.nuget.org/v3/index.json
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
Attempting to gather dependency information for multiple packages with respect to project 'D:\src\test\nugetUpdate\test\test.vcxproj', targeting 'native,Version=v0.0'
Gathering dependency information took 323 ms
Attempting to resolve dependencies for multiple packages.
Resolving dependency information took 0 ms
Resolving actions install multiple packages
Resolution was successful but resulted in no action
There are no new updates available.
No package updates are available from the current package source for project 'D:\src\test\nugetUpdate\test\test.vcxproj'.
Executing nuget actions took 6 ms
The error message you copied into this issue, was it from running the test.sln you provided, or was it actually from your "real" project, and you assumed it'd still happen with test.sln? If you run nuget.exe from within a "Developer Command Prompt for VS" or "Developer PowerShell for VS", does it still happen?
If you happen to have experience using fuslogvw, I think it would be interesting to see which which dlls were being loaded, and their full paths. As you pointed out, this happens when Microsoft.Build.dll or Microsoft.IO.Redist.dll were compiled against a different version of Microsoft.Memory.dll than was loaded. There's a community created fuslog++ which I've heard is much easier to use, but I've never tried it myself. Another option is to use PerfView.exe to record nuget.exe's execution. I don't remember if it's necessary to enable the ".NET Loader" collector to include assembly load information, but it wouldn't hurt. However, the etl.zip file it will record will be huge, so fuslog will result in much smaller logs to share.
Looking at the vcxproj
, I think this is not a C++/CLI project, so it's unlikely you have microsort.build.dll, system.memory.dll or microsoft.io.redist.dll is your project's bin\
directory. I'm not sure what else the problem might be,
Hi @zivkan, I just replicated the issue by:
nuget restore
C:\src\test>nuget restore
MSBuild auto-detection: using msbuild version '17.7.2.37605' from 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\bin'.
Restoring NuGet package gtest.1.7.0.
Adding package 'gtest.1.7.0' to folder 'C:\src\test\packages'
Added package 'gtest.1.7.0' to folder 'C:\src\test\packages'
NuGet Config files used: C:\Users\mnixon\AppData\Roaming\NuGet\NuGet.Config C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config C:\Program Files (x86)\NuGet\Config\Xamarin.Offline.config
Feeds used: C:\Users\mnixon.nuget\packages\ https://api.nuget.org/v3/index.json C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
Installed: 1 package(s) to packages.config projects
3. Then running `nuget update test.sln`
C:\src\test>nuget update test.sln
MSBuild auto-detection: using msbuild version '17.7.2.37605' from 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\bin'.
Scanning for projects...
Method not found: 'System.ReadOnlySpan1<Char> Microsoft.IO.Path.GetFileName(System.ReadOnlySpan
1
---
Update: The problem appears to be that the NuGet 6.6.1.2 I was using happened to be in a folder that also contained the `System.Memory.dll (4.5.5)` for net461. If I copy the NuGet.exe to a different folder and put that folder earlier in the path then everything seems to work.
Thanks for getting back to us!
There is some docs on how the .NET Framework runtime locates assemblies: https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies
To be honest, I didn't read it carefully. Doing very quick search, it appears to say that if the referenced assembly is not strong named, then the runtime only checks the application directory, and later when it gives a 4 step list on how it loads strong named assemblies, it doesn't mention the application directory.
In any case, I'm going to close is as by design, as this is just how the .NET Framework runtime works.
NuGet Product Used
NuGet.exe
Product Version
6.6.1.2
Worked before?
No response
Impact
I'm unable to use this version
Repro Steps & Context
nuget restore
to restore packagesnuget update test.sln
and (Generates Method not found exception)nuget update test.sln -MSBuildVersion 14
and observe command workstest.zip
Verbose Logs