Roslyn method survey - Loading a solution with MsBuild
I wanted to survey all method signatures in a codebase. I split the problem into two: loading the solution; and indexing all methods. The first turned out to be a complete rabbit hole. The documentation around MsBuild is a morass of partially-incomplete, somewhat misleading treacle; I’ve summarised some points here. MsBuild is also passive aggressive at best. If something doesn’t work, it won’t tell you - you have to know how to ask it.
MsBuild
Using MsBuild from C# is relatively easy; however, a lot of information out there concerns itself with finding a version of MsBuild to use from code that mostly relates to older versions of MsBuild - and which are actively obstructive today. Nowadays you can just include a dependency on the NuGet Microsoft.Build.Locator
. If you’re using Rider, as I am, you might not have installed the Microsoft build tools, but they can be downloaded as a standalone installer from Microsoft’s all MsBuild downloads page.
So, to cut to the solution create a CSharp executable project, add NuGet packages:
Microsoft.Build.Framework
Microsoft.Build.Tasks.Core
Microsoft.Build
Microsoft.CodeAnalysis.Workspaces.MSBuildWorkspace
Microsoft.CodeAnalysis.CSharp
Microsoft.CodeAnalysis.CSharp.Workspaces
and then, importantly, initialise the MsBuildLocator before calling any methods that use it; a small, but interesting wrinkle that I didn’t get immediately. This example from Microsoft was crtically useful in getting me (re)started.
Then add a method that we can use to load all syntax-api-supporting documents in the solution … with some NuGets and helpful comments along the way:
NuGet.Frameworks
NuGet.ProjectModel
NuGet.Packaging
Finally - you need to mark the Microsoft.Build.*
assets with ExcludeRuntime=true
tags in your project file - this avoids having MsBuild assemblies copied to your build directory and allows the locator to reference them indirectly:
and you’re there: congratulations! In a few minutes you’ve achieved what took me a number of grinding, painful hours :)