From the .NET blog...

In case you missed it earlier...

AI-Powered MSBuild Investigation with the Microsoft Binlog MCP Server
https://devblogs.microsoft.com/dotnet/msbuild-binlog-mcp-server/ #dotnet #AI #binlog #builddiagnostics #GitHubCopilot #MCP #ModelContextProtocol #msbuild

RE: https://hachyderm.io/@tmeschter/116751973349195922

There's another option for getting information out of MSBuild that I didn't cover before because the thread was getting long: `-getTargetResult`.

In MSBuild a target can (optionally) return a set of items. This lets you treat it as a function, not just a "unit of work".

For example, you can run:
`dotnet build -getTargetResult:ResolveReferences`

and get
```
{
"TargetResults": {
"ResolveReferences": {
"Result": "Success",
"Items": [
{
"Identity": "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\10.0.8\\ref\\net10.0\\Microsoft.CSharp.dll",
"FileVersion": "10.0.826.23019",
...
},
{
"Identity": "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\10.0.8\\ref\\net10.0\\Microsoft.VisualBasic.Core.dll",
"FileVersion": "15.0.826.23019",
...
},
...
]
}
}
}
```
which is a list of all the references being passed to the C# compiler, along with a bunch of metadata on each.

Or you can run the "Build" target and get information about the outputs:
```
> dotnet build -getTargetResult:Build
{
"TargetResults": {
"Build": {
"Result": "Success",
"Items": [
{
"Identity": "C:\\Users\\me\\source\\repos\\TestConsole\\TestConsole\\bin\\Debug\\net10.0\\TestConsole.dll",
"ReferenceAssembly": "C:\\Users\\me\\source\\repos\\TestConsole\\TestConsole\\obj\\Debug\\net10.0\\ref\\TestConsole.dll",
"FullPath": "C:\\Users\\me\\source\\repos\\TestConsole\\TestConsole\\bin\\Debug\\net10.0\\TestConsole.dll",
...
}
]
}
}
}
```

So depending on the target that can be another option.

#msbuild #dotnet #csharp

AI-Powered MSBuild Investigation with the Microsoft Binlog MCP Server - .NET Blog

Diagnose MSBuild build failures and performance issues with AI using the new Microsoft Binlog MCP Server - 15 specialized tools that let your AI assistant investigate binary logs.

.NET Blog

From the .NET blog...

AI-Powered MSBuild Investigation with the Microsoft Binlog MCP Server
https://devblogs.microsoft.com/dotnet/msbuild-binlog-mcp-server/ #dotnet #AI #binlog #builddiagnostics #GitHubCopilot #MCP #ModelContextProtocol #msbuild

AI-Powered MSBuild Investigation with the Microsoft Binlog MCP Server - .NET Blog

Diagnose MSBuild build failures and performance issues with AI using the new Microsoft Binlog MCP Server - 15 specialized tools that let your AI assistant investigate binary logs.

.NET Blog

So what practical things might you do with `-getProperty` and `-getTarget`?

Say you have some logic to dynamically set the `Version` during a build. If you wanted to check the version you could build the whole project with `dotnet build` and then find and crack open the resulting .dll... or you could run just the target that computes the version and output the result:
```
dotnet build -getProperty:Version -target:ComputeVersion
```
Alternatively you might want to compile a list of your top-level NuGet dependencies. In this case you can loop over all your .csproj files and run:
```
dotnet build -getItem:PackageReference <path_to_csproj>
```

This is potentially useful in any situation where you want to extract structured information from a build that isn't included in the build output, or you don't want to pay the cost of a full build.

#dotnet #msbuild #csharp

So far we've just used `-getProperty` and `-getItem` to query the "evaluation" phase of MSBuild--basically, the step where MSBuild finds and understands all the inputs to your project's build. To actually *do* anything we need to go a step further and execute one of the build targets:

```
> dotnet build -getItem:Compile -target:Compile
{
"Items": {
"Compile": [
{
"Identity": "Program.cs",
...
},
{
"Identity": "obj\\Debug\\net10.0\\TestConsole.GlobalUsings.g.cs",
...
},
{
"Identity": "obj\\Debug\\net10.0\\.NETCoreApp,Version=v10.0.AssemblyAttributes.cs",
...
},
{
"Identity": "obj\\Debug\\net10.0\\TestConsole.AssemblyInfo.cs",
...
}
]
}
}
```
(Don't get confused by "Compile" appearing twice. We're running the "Compile" *target* and then retrieving the "Compile" *items*; these are two distinct things that just happen to share a name in this example.)

We can see here that in the course of running the target the build created three new "Compile" items to hold the global "usings" and various assembly-level attributes.

#dotnet #msbuild #csharp

What if you want to see the actual code files involved?

```
> dotnet build -getItem:Compile
```

For a new console application this will show a single item:

```
{
"Items": {
"Compile": [
{
"Identity": "Program.cs",
"FullPath": "C:\\Users\\me\\source\\repos\\TestConsole\\TestConsole\\Program.cs",
"RootDir": "C:\\",
"Filename": "Program",
"Extension": ".cs",
"RelativeDir": "",
"Directory": "Users\\me\\source\\repos\\TestConsole\\TestConsole\\",
"RecursiveDir": "",
"ModifiedTime": "2026-06-14 19:57:18.0522787",
"CreatedTime": "2026-06-14 19:57:18.0492830",
"AccessedTime": "2026-06-14 19:57:19.2281805",
"DefiningProjectFullPath": "C:\\Program Files\\dotnet\\sdk\\10.0.204\\Sdks\\Microsoft.NET.Sdk\\targets\\Microsoft.NET.Sdk.DefaultItems.props",
"DefiningProjectDirectory": "C:\\Program Files\\dotnet\\sdk\\10.0.204\\Sdks\\Microsoft.NET.Sdk\\targets\\",
"DefiningProjectName": "Microsoft.NET.Sdk.DefaultItems",
"DefiningProjectExtension": ".props"
}
]
}
}
```

And Program.cs is of course the one file in the project directory.

However, Program.cs is *not* the only C# file that is passed to the compiler when you build!

#dotnet #msbuild #csharp

Similarly, you can get project items with `-getItem`:

```
> dotnet build -getItem:PackageReference
{
"Items": {
"PackageReference": [
{
"Identity": "Errata",
"Version": "0.16.0",
"FullPath": "C:\\Users\\me\\...",
"RootDir": "C:\\",
"Filename": "Errata",
"Extension": "",
"RelativeDir": "",
"Directory": "Users\\me\\...",
"RecursiveDir": "",
"ModifiedTime": "",
"CreatedTime": "",
"AccessedTime": "",
"DefiningProjectFullPath": "C:\\Users\\me\\...\\beta\\beta.csproj",
"DefiningProjectDirectory": "C:\\Users\\me\\...\\beta\\",
"DefiningProjectName": "beta",
"DefiningProjectExtension": ".csproj"
},
{
"Identity": "RadLine",
"Version": "0.10.0",
...
},
{
"Identity": "Spectre.Console",
"Version": "0.55.1",
...
}
]
}
}
```

This gets you all the PackageReference items in your project, including their metadata.

#msbuild #dotnet #csharp

Let's talk about extracting information from MSBuild-based projects, like C# projects (.csproj).

I have no particular reason to do this; I just think it's cool. However, this might be useful to extract information from your build system without needing to run a full build, or as an alternative to having more complicated MSBuild logic to create an output file.

Starting in .NET 8 you can run:

```
dotnet build -getProperty:Foo
```

Instead of running a build, this will output the value of the "Foo" property. For example:

```
> dotnet build -getProperty:TargetFramework
net9.0
```

You can ask for multiple properties, in which case dotnet will return a JSON object:

```
> dotnet build -getProperty:TargetFramework,OutputType
{
"Properties": {
"TargetFramework": "net9.0",
"OutputType": "Exe"
}
}
```

#msbuild #dotnet #csharp