Skip to content
New issue

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

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

Already on GitHub? # to your account

MSBuildWorkspace: "No assembly containing System.Object was found" when using Roslyn to build a class library loaded from csproj #26029

Closed
FizzerWL opened this issue Apr 9, 2018 · 13 comments
Assignees

Comments

@FizzerWL
Copy link

FizzerWL commented Apr 9, 2018

Hello,

Since updating my version of VS, I can no longer use Roslyn to build class libraries. Using MSBuildWorkspace.Create().OpenSolution doesn't seem to load the project references, resulting in the error "No value for RuntimeMetadataVersion found. No assembly containing System.Object was found".

I have created a repro sample that demonstrates the problem. This has two solutions: A simple class library solution with two projects, one that references the other. The second solution is a roslyn app that loads the first solution with MSBuildWorkspace.Create().OpenSolution and tries to build it.

Version Used: Visual Studio Community 15.6.5

Steps to Reproduce:

  1. Clone minimal repro solution at https://github.com/FizzerWL/ErrorRepro
  2. Open Builder/Builder.sln
  3. Build+Run

Expected Behavior: Program runs without errors.

Actual Behavior: Program fails and outputs tons of errors, caused by references not being loaded:

Unhandled Exception: System.Exception: Build failed. 47 errors:
warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Class1.cs(1,7): error CS0246: The type or namespace name 'System' could not be found

Full output

Other references to this error message on Stackoverflow and such suggest manually adding a reference to mscorlib to fix the error. However, this should not be necessary since all references should be automatically loaded out of the csproj file.

Thank you!

@jmarolf
Copy link
Contributor

jmarolf commented Apr 9, 2018

@DustinCampbell but I suspect this has to do with MSBuild binding redirects.

@DustinCampbell DustinCampbell self-assigned this Apr 10, 2018
@wbalbal
Copy link

wbalbal commented Apr 10, 2018

#25679 this is it i guess.

@DustinCampbell
Copy link
Member

Thanks for a great repro @FizzerWL! I've submitted a PR to your repo that shows how to make MSBuildWorkspace work in your repro application: FizzerWL/ErrorRepro#1.

Here are the changes that my PR needed to make to your application:

  1. The Microsoft.Build.* assemblies need to be deleted from your output folder.

    These are actually the real problem. Today, the package that includes MSBuildWorkspace pulls the MSBuild dlls into your application. However, those are almost certainly different than the ones required by the MSBuild toolset included in Visual Studio.

  2. Use the Microsoft.Build.Locator package to find and register an instance of Visual Studio 2017.

    Now that your application doesn't include the Microsoft.Build*, it needs to find them somewhere. The Microsoft.Build.Locator package handles that for you. Once an instance of Visual Studio 2017 is registered, the locator adds an AppDomain.AssemblyResolve hook to load the Microsoft.Build.* from that instance of Visual Studio 2017. That way, the assemblies will match what's expected by the MSBuild toolset.

@DustinCampbell DustinCampbell changed the title "No assembly containing System.Object was found" when using Roslyn to build a class library loaded from csproj MSBuildWorkspace: "No assembly containing System.Object was found" when using Roslyn to build a class library loaded from csproj Apr 10, 2018
@FizzerWL
Copy link
Author

It worked, thank you!

@mwpowellhtx
Copy link

Running into the same issue during our Roslyn based CG pipeline. Unable to even run an embedded Compilation during our unit tests now. The error is literally,

[CS8021]: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.

Apparently broken or confused since loading a side-by-side VS2019 with VS2017. Prior to that our Roslyn compilations, etc, worked just fine in our pipeline.

So, you're saying that we need to load the Build assemblies via locator instead? Is there an example?

@jmarolf
Copy link
Contributor

jmarolf commented Oct 23, 2019

@mwpowellhtx see the example console app here

@mwpowellhtx
Copy link

Thanks. We got past this bit, but now Roslyn is seemingly not producing any diagnostics for code that we think it should. That or perhaps we are not calling the correct methods, have not provided Roslyn with the correct options, workspace properties, etc.

@mwpowellhtx
Copy link

@jmarolf Interesting, so it is more appropriate to route actual solutions/projects through an instance of Visual Studio? how about for usage of the Roslyn API itself?

@jmarolf
Copy link
Contributor

jmarolf commented Oct 24, 2019

so it is more appropriate to route actual solutions/projects through an instance of Visual Studio?

@mwpowellhtx The example file I linked to shows the correct way to find MSBuild on a machine with several different versions installed. This is needed if you want to use the roslyn apis to analyze symbolic information in a stand-alone tool that is not loaded by visual studio. If you do not need to tool to run on separately from VS you can write an VS extension that load the VisualStudioWorkspace via MEF.

If you do not need any semantic information and can rely on purely syntactic data you can just use CSharpSyntaxTree.ParseText.

As for what is most appropriate, that depends on the general thing you are trying to accomplish. Generally people find the stand-alone-tool route the simplest and most flexible.

@mwpowellhtx
Copy link

@jmarolf Hmm, I see; well this assumes a lot about where we are headed with this usage, doesn't it? To which I respond, where are we headed with it? Ultimately we are generating code during the build pipeline. So, this is interesting, but really what we want is are the NuGet packages, etc.

@jmarolf
Copy link
Contributor

jmarolf commented Oct 24, 2019

@mwpowellhtx I see, so you are doing something like CodeGeneration.Roslyn? Their approach is to create a nuget package with props and targets files that call your tool on build (see here for instructions and here for the target file they use). I think an approach like this should work for you.

The thing you ultimately need is to construct a compilation. CodeGeneration.Roslyn does this by having MSBuild pass all the compilation info to their tool (here) and then construct a new compilation object from these arguments (here).

@mwpowellhtx
Copy link

@jmarolf Indeed, Code.Generation.Roslyn, and sometimes fit-for-purpose CG, that is, not plugging in to the Generator API.

@mwpowellhtx
Copy link

@jmarolf To be clear, the tact we are taking with CGR is to facilitate only, not to infer anything about name spaces, etc. Another key difference is that we allow CG to happen at the assembly level. And last but not least, nor exhaustive, we allow multiple CompilationUnitSyntax to be generated.

oliwennell pushed a commit to ComparetheMarket/fettle that referenced this issue Jan 14, 2020
* #15: Add new, simple project not linked to fettle in any way (has its own solution, not within fettle solution) which uses .NET 4.5.2 to try to reproduce issue

* #15: Add System.ValueTuple nuget package to new project as well

* #15: Make the new comparison class for ValueTuple static

* Attempt to fix problem related to RuntimeMetadataVersion not found, based on dotnet/roslyn#26029 - helps with at least one project, although now a null ref error is returned instead :homer_thinking::homer_disappear:

* PH: Revert to previous operation if no VS instances found, as would be the case on an AWS instance :womble:

* PH: Update paket to latest version, revert change on MSBuildWorkspaceFactory as RegisterDefaults uses the default VS instance anyway; most importantly, add reference to Microsoft.Build.Locator to Console app as this seems to stop all of the System.Object and related errors :disco:. It still fails to do the actual analysis but.. progress :man-shrugging:

* ✨ Allow filtering on project filePaths
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants