CLI tool
Buildalyzer/Buildalyzer avatar
Buildalyzer/Buildalyzer

Buildalyzer runs MSBuild for you and stops before the compiler runs

A utility to perform design-time builds of .NET projects without having to think too hard about it.

688 stars107 forksC#MIT

At a glance

What is it?
Buildalyzer/Buildalyzer is an MIT licensed .NET library that lets your own code invoke MSBuild, by default in design-time mode so you get resolved references, source files and properties without paying for a full compile, and it ships a second package for building a Roslyn Workspace. The cost is that you are configuring MSBuild yourself, and the README warns that changing the global properties can break loading and compilation.
Who is it for?
Adopt Buildalyzer if you are building tooling on top of MSBuild and need the evaluated project, with its resolved references, items and properties, without invoking the compiler on every query, since that is exactly the gap it fills and the reason it exists.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 39 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A design-time build, which is cheaper than a real one

Buildalyzer is described as a utility to perform design-time builds of .NET projects without having to think too hard about it, and the mechanism explains the name. By default it runs a design-time build, which the README says is higher performance than a normal build because it doesn't actually try to compile the project. What you get instead is the evaluation of the project: which files the compiler would see, which references resolve, what the MSBuild properties evaluate to. The second design decision is the process boundary. Buildalyzer runs MSBuild out-of-process, and the README says it therefore should work anywhere, anytime, and on any platform you can build the project yourself manually on the command line. That is a portability claim with a clear condition attached, and the condition is the one you should test first, since a design-time build inherits whatever your command line build already needs.

Two classes, and the whole API fits in five lines

The usage section names the two main classes, AnalyzerManager and ProjectAnalyzer, and the relationship between them. The AnalyzerManager class coordinates loading each individual project and consolidates information from a solution file if provided. The ProjectAnalyzer class figures out how to configure MSBuild and uses it to load and compile the project in design-time mode. The example shows the whole path:

csharp
AnalyzerManager manager = new AnalyzerManager();
IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");
IAnalyzerResults results = analyzer.Build();
string[] sourceFiles = results.First().SourceFiles;

There are two conveniences worth knowing. Passing the solution path as the first argument of the AnalyzerManager constructor parses the solution file and executes GetProject for each project it finds, so a whole solution loads in one call. And calling GetProject again for the same project path returns the existing ProjectAnalyzer rather than building a second one, while the IReadOnlyDictionary property AnalyzerManager.Projects lets you iterate over every analyzer that has been loaded. That caching behaviour is what makes it reasonable to ask several questions about the same project.

Results are per target framework, and the properties are the payload

Calling Build() returns an AnalyzerResults object, which is a collection of AnalyzerResult objects for each of the target frameworks that were built, and the README notes it will usually contain a single result unless the project is multi-targeted. Each result exposes the evaluated project. TargetFramework gives the framework of that particular result. SourceFiles gives the full path of all resolved source files, References the full path of all resolved references, and ProjectReferences the full path of the project file for each resolved project reference. Properties is an IReadOnlyDictionary of all MSBuild properties from the project, with GetProperty returning a single value by name. Items is an IReadOnlyDictionary of all MSBuild items, where each ProjectItem carries the item specification as ItemSpec and all of its metadata in a separate dictionary. For a tool that wants to reason about a project rather than build it, those two dictionaries are the interesting part, because they are the evaluated state of the build.

Global properties are the knob, and the footgun

Buildalyzer sets some MSBuild properties to make loading and compilation work the way it needs, for example to trigger a design-time build, and you can see them through the IReadOnlyDictionary property ProjectAnalyzer.GlobalProperties. The README then gives two ways to change them before loading or compiling. AnalyzerManager.SetGlobalProperty and RemoveGlobalProperty set the global properties for all projects loaded by that manager, while ProjectAnalyzer.SetGlobalProperty and RemoveGlobalProperty set them for just that one project. The warning that follows is the important sentence: you may break the ability to load, compile, or interpret the project if you change the MSBuild properties. That is not a theoretical caution, because the design-time build depends on a specific property configuration, and the same mechanism that lets you fix a project that loads badly lets you break one that loaded fine. Treat the property set as part of the contract with the tool.

Two packages on NuGet, both on .NET Standard 2.0

Installation is the standard NuGet route, and there are two packages because there are two jobs. The base package installs like this:

bash
$ Install-Package Buildalyzer

or through the.NET Core CLI:

bash
$ dotnet add package Buildalyzer

The second package, Buildalyzer.Workspaces, exists to create a Roslyn Workspace, and it has its own pair of commands:

bash
$ Install-Package Buildalyzer.Workspaces
bash
$ dotnet add package Buildalyzer.Workspaces

Both packages target.NET Standard 2.0, which is what makes them consumable from.NET Framework and.NET applications alike, and it is also the reason the tool can drive MSBuild on any platform where you can build the project from the command line. The README links two blog posts that explain the motivation and the mechanics in more depth, one on running a design-time build with the MSBuild APIs and one on MSBuild loggers and logging events,

Single file publishing needs two logger assemblies

One deployment detail in the README is easy to miss and annoying to discover late. If your application's output is a single file, you will need to provide the path to two DLLs, MsBuildPipeLogger.Logger.dll and Buildalyzer.logger.dll. The reason is structural rather than incidental: Buildalyzer drives MSBuild out of process, and MSBuild logging travels over a pipe, so the logger assemblies have to be present and locatable at run time. A single file publish tends to gather dependencies into one bundle, and the loading assumptions of these two components do not survive that. If you ship a tool built on Buildalyzer as a self-contained executable, this is the failure you will hit, and the fix is to keep those two files alongside the executable rather than bundling them.

A modern .NET repository with a dated release line

The repository layout matches a current .NET project. There is buildalyzer.slnx, the newer solution file format, a .net.csproj at the root, Directory.Build.props and package.props for shared build settings, a stylecop.json and a .globalconfig for style and analyzer configuration, an .editorconfig, a NuGet.config, azure-pipelines.yml for continuous integration, a RELEASE.md for the release process, and src/ and tests/ directories. The licence is MIT, with LICENSE.md at the root. The release history is the part to note. Version 7.1.0 came on 2024-11-16, 8.0.0 on 2025-12-17 and 9.0.0 on 2026-04-18, so the major version tracks the .NET generation rather than the feature set, which is a good sign for a library whose whole job is tracking MSBuild. The repository is not archived and the last push was on 2026-09-14, and the project is sponsored by Amazon Web Services, which is explained in the README as covering the .NET language support AWS offers.

Using the MSBuild APIs directly is the alternative

The alternative is to call the MSBuild evaluation APIs yourself, and the README points at exactly that approach, since the blog post it links is titled running a design-time build with MSBuild APIs. The difference in approach is where the work sits. Doing it yourself means constructing the evaluation, wiring the MSBuild loggers yourself, and handling the pipe and process plumbing that Buildalyzer handles for you, which is exactly the work the author wrote the library to avoid. What you gain is full control over the build configuration and no dependency on the library's defaults, and what you give up is the design-time property configuration, the solution level coordination and the per target framework result objects that come ready made. For a tool that needs one project's evaluated properties once, the direct route is defensible. For a tool that loads a solution and answers many questions about many projects, the caching in AnalyzerManager and the results model are worth more than the dependency.

Editorial conclusion

Adopt Buildalyzer if you are building tooling on top of MSBuild and need the evaluated project, with its resolved references, items and properties, without invoking the compiler on every query, since that is exactly the gap it fills and the reason it exists. Do not adopt it if you only need to run a build, because a plain MSBuild invocation is simpler, and do not expect it to hide MSBuild from you, since the global properties it sets are yours to change and the README is blunt about the risk of breaking loading. Before you integrate, check that the target framework and the MSBuild version on the machine match the ones Buildalyzer drives, and remember the two logger assemblies that a single file published application has to carry alongside the library.

Frequently asked questions

What is Buildalyzer and what does a design-time build give me?

Buildalyzer lets you run MSBuild from your own code and returns information about the project. By default it runs a design-time build, which the README says is higher performance than a normal build because it does not actually try to compile the project, and you get resolved references, source files and MSBuild properties instead.

How do I install Buildalyzer and Buildalyzer.Workspaces?

Both are on NuGet. Use Install-Package Buildalyzer or dotnet add package Buildalyzer for the base library, and the same two commands with Buildalyzer.Workspaces for the Roslyn Workspace support. Both packages target .NET Standard 2.0.

How do I load every project in a solution with Buildalyzer?

Pass the solution path as the first argument of the AnalyzerManager constructor, and it parses the solution file and calls GetProject for each project it finds. Calling GetProject again for the same path returns the existing ProjectAnalyzer, and the AnalyzerManager.Projects dictionary holds every loaded analyzer.

What do I get back from ProjectAnalyzer.Build()?

An AnalyzerResults object, which is a collection of AnalyzerResult objects, one per target framework that was built, usually a single one unless the project is multi-targeted. Each result exposes SourceFiles, References, ProjectReferences, Properties as a dictionary, GetProperty for a single value, and Items as a dictionary of ProjectItem with ItemSpec and Metadata.

What has to change when I publish my app as a single file?

You have to provide the paths to MsBuildPipeLogger.Logger.dll and Buildalyzer.logger.dll, because Buildalyzer runs MSBuild out of process and the logging travels over a pipe, so those assemblies have to be present alongside the executable.

Official sources

  1. Buildalyzer/Buildalyzer on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/buildalyzer-buildalyzer.svg)](https://hysenlabs.com/projects/buildalyzer-buildalyzer)

Was this useful?