Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could not load file or assembly NuGet.Frameworks #240

Closed
ricardoboss opened this issue Nov 24, 2023 · 16 comments
Closed

Could not load file or assembly NuGet.Frameworks #240

ricardoboss opened this issue Nov 24, 2023 · 16 comments
Labels
⚠ Bug Something isn't working as expected

Comments

@ricardoboss
Copy link

ricardoboss commented Nov 24, 2023

I'm getting runtime errors like the one described in dotnet/roslyn#61454.

Debugging works when I load the Nuget.Frameworks namespace before calling any code by buildalyzer...

Not sure what is going on. Maybe I can provide a minimal example to reproduce the issue.
I think it is related to .NET 8, since it is the last thing I changed in my toolchain.

The exception I am getting is:

System.TypeInitializationException: The type initializer for 'Buildalyzer.TargetFrameworkComparer' threw an exception.
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'NuGet.Frameworks, Version=6.0.0.280, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.

File name: 'NuGet.Frameworks, Version=6.0.0.280, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
   --- End of inner exception stack trace ---
   at Buildalyzer.AnalyzerResults.get_TargetFrameworks()
   at Buildalyzer.AnalyzerResults.get_Results()
   at Buildalyzer.AnalyzerResults.GetEnumerator()
   at <my project source code>
@daveaglick
Copy link
Collaborator

A reproducible example is always really helpful. There's a lot of good discussion in the linked issue as well. At first glance, it looks like this is likely a binding failure, either because we're looking for the Nuget.Frameworks package in the wrong place, or because the SDK is providing a different version than what we're trying to bind to.

The best long-term solution is likely going to be to remove the dependency entirely since it looks like it's problematic. I'll have to look at where it's used, but if it's only being used to get a list of framework monikers, then taking it out shouldn't be too bad (provided I can find a good way to keep up with those otherwise).

@daveaglick daveaglick added the ⚠ Bug Something isn't working as expected label Nov 28, 2023
@ricardoboss ricardoboss changed the title Remove dependency on NuGet.Frameworks Could not load file or assembly NuGet.Frameworks Nov 28, 2023
@bhugot
Copy link
Contributor

bhugot commented Dec 15, 2023

I got same problem when running a test that use Buildalyzer

System.TypeInitializationException: The type initializer for 'Microsoft.VisualStudio.TestPlatform.ObjectModel.Framework' threw an exception.
---> System.IO.FileNotFoundException: Could not load file or assembly 'NuGet.Frameworks, Version=6.5.0.154, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
File name: 'NuGet.Frameworks, Version=6.5.0.154, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
at Microsoft.VisualStudio.TestPlatform.ObjectModel.Framework.FromString(String frameworkString)
at Microsoft.VisualStudio.TestPlatform.ObjectModel.Framework..cctor() in //src/Microsoft.TestPlatform.ObjectModel/Framework.cs:line 31
--- End of inner exception stack trace ---
at Microsoft.VisualStudio.TestPlatform.ObjectModel.Framework.get_DefaultFramework() in /
/src/Microsoft.TestPlatform.ObjectModel/Framework.cs:line 31

@daveaglick
Copy link
Collaborator

Thanks for the report @ricardoboss and @bhugot. I've got the .NET 8 SDK installed and don't see this, at least with any of the Buildalyzer test projects. That might be due to how the test harness runs, like perhaps it uses a different binding or something. A reproduceable example would be really helpful here.

Even better would be if one (or both) of you could check out the just-release Buildalyzer 6.0.0 version and see if that resolves the problem. I merged some PRs that update references, so it's possible whatever was failing to bind correctly here is now fixed in that release.

@bhugot
Copy link
Contributor

bhugot commented Dec 19, 2023

Hello not better.
To be more explicit on the use case we run a nunit test that load all project to verify dependencies of project by creating TestCase for each project.
It's working in 7.0

@ricardoboss
Copy link
Author

I am trying to reproduce it, but so far I have only seen the error occur in packed release builds. I am using Buildalyzer in a dotnet tool. This is my current workaround: https://github.com/ricardoboss/cranky/blob/415633e688180f88904c2cdc9db68779ac294f27/Cranky/Analyzer.cs#L41

The problem is... well I can't reproduce it. I tested it with .NET 8 on macOS and Windows without the workaround and it worked. I checked out the first commit where I introduced the workaround and removed it; still - it worked. I tested it with an older version of Buildalyzer - works. I tested the latest version - works.

So... yeah. Maybe its something with the toolchain in .NET 7/8 that breaks it.

@bhugot my workaround might help you too. You need to load the assembly (implicitly) before calling any code from Buildalyzer. I used this small snippet:

_ = NuGetFramework.AnyFramework;

As this loads the NuGet.Frameworks assembly.

Also, I added this to my package references:

<PackageReference Include="NuGet.Frameworks" Version="6.8.0" IncludeAssets="All" />

I think the IncludeAssets="All" part is important here.

@ricardoboss
Copy link
Author

Nevermind, my testing methodology seems flawed. I'm gonna try and isolate the problem. It seems I need to run dotnet clean before running again.

The first thing I noticed was that Nuget.Frameworks.dll is missing after the clean (and without the workaround). Also fails with 6.0.0.

@ricardoboss
Copy link
Author

It turns out if you run Buildalyzer on the project itself (the project using Buildalyzer), not yet loaded DLLs are removed from the folder which you are currently running in.

In my case Nuget.Frameworks.dll was not used before Buildalyzer ran and was therefore removed. When I run my tool with other projects it works.

This is my example app to test this behavior: https://github.com/ricardoboss/BuildalyzerDependencyHell

@daveaglick
Copy link
Collaborator

After some research, I think I'm just going to remove the dependency on NuGet.Frameworks altogether. It's only being used to parse a framework name for the purpose of sorting them, and I think that can be done just as easily with a string comparison. It may not be quite as accurate, but the sort order just needs to be deterministic, not in some special framework order.

Thanks for linking the corresponding issue over in the SDK - I think we could probably resolve it using some derivative of the approach that other similar tools have taken and delete the assemblies from the Buildalyzer package before packing so that our version isn't picked up and only the Roslyn/SDK version can be bound, but just eliminating the problem in the first place by removing the package seems easier.

@daveaglick
Copy link
Collaborator

Buildalyzer 6.0.1 should be up on NuGet now and that'll resolve this by totally removing the reference.

@bhugot
Copy link
Contributor

bhugot commented Dec 21, 2023

Sorry but the problem is not there because I still have the problem

@daveaglick
Copy link
Collaborator

Sorry but the problem is not there because I still have the problem

You're kidding?! At this point I'm totally stumped then. 6.0.2 has no references at all on any NuGet packages (including transitive - this tool window shows the whole dependency graph):

image

Is it possible some old assemblies are still hanging around in your output folder? What happens if you totally delete the bin and obj directories and then rebuild? Or any chance your calling application has some NuGet references directly?

@bhugot
Copy link
Contributor

bhugot commented Dec 22, 2023

It's not the problem of package in Buildalyzer.

@bhugot
Copy link
Contributor

bhugot commented Dec 29, 2023

@daveaglick the problem happened somewhere during the execution of GetWorkspace() method.

I looked at the bin directory a big part of dll is removed during GetWorkspace() execution the solution is integrating the project that do the run.

AnalyzerManager manager = new(SolutionPath);
var workspace = manager.GetWorkspace();

@0xced
Copy link
Contributor

0xced commented Jan 6, 2024

This is my example app to test this behavior: https://github.com/ricardoboss/BuildalyzerDependencyHell

The System.IO.FileNotFoundException occurs because analyzer.Build() cleans the bin/Debug/net8.0 directory, including the NuGet.Frameworks.dll file. So this is not a dependency hell problem kind as it used to occur on .NET Framework. Actually, running the BuildalyzerDependencyHell sample on any other csproj but BuildalyzerDependencyHell.csproj will work just fine.

@ricardoboss
Copy link
Author

@0xced yes that's right. I created the example before I knew the actual problem. Nevertheless, the repository in its current form reproduces the problem.

@daveaglick
Copy link
Collaborator

Ahh...this makes more sense now! So the issue likely wasn't ever related directly to NuGet.Frameworks, though there have been some issues with binding that particular assembly reported elsewhere, and removing the single point of reference to it likely wasn't a bad idea anyway (#242 excepted).

In this case, cleaning vs. not cleaning has turned out to be a really tough problem over the years. There's a much longer discussion in #105 with some things to try. I'm not inclined to completely change the current behavior to drop the clean target, especially since MSBuild seems to like cleaning even without that target in some scenarios (see the linked issue). I'm not sure what the "right" answer is here. Someone in #105 suggested changing the bin output folder for Buildalyzer builds and while that's not perfect, it does seem to help - at least in this specific scenario where you're trying to run Buildalyzer on the project that's currently executing.

Since NuGet.Frameworks has been removed, and there's already (at least) one issue on the topic of cleaning, let's go ahead and leave this specific issue as closed - any ongoing discussion on cleaning can continue to happen in #105.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚠ Bug Something isn't working as expected
Projects
None yet
Development

No branches or pull requests

4 participants