Using MSBuild.exe /bl to record a binary log
MSBuild 15.3 introduces a new command-line switch: /bl to record all build events to a structured/binary log file:
Double-click the .binlog file to open it in MSBuild Structured Log Viewer:
Using dotnet build -bl to record a binary log
You can also produce binary logs from the dotnet build command by passing the -bl argument:
dotnet build -bl
Using MSBUILDDEBUGENGINE=1 to get full binlogs from Visual Studio
There are known limitations in binlogs obtained via the Project System Tools. Instead, try setting the MSBUILDDEBUGENGINE=1 environment variable as described here.
You can install the Visual Studio Project System Tools Extension (unsupported) to investigate builds inside Visual Studio:
Replaying a .binlog to reconstruct text logs
You can pass a .binlog file to MSBuild instead of a project/solution to replay it to other loggers, as if a real build was happening. This allows you to reconstruct a text log of any verbosity given the .binlog file. Read more at: https://github.com/Microsoft/msbuild/wiki/Binary-Log#replaying-a-binary-log
Binary log advantages
- Completeness - records the exact events in order they happened during the build. You can replay a binary log into other loggers to reconstruct full text logs. Pass the .binlog file to MSBuild.exe instead of a project/solution to replay the log as if the original build was happening.
- Verbosity - binary logs capture more information than even the most diagnostic-level text logs. The binary logger turns on various MSBuild switches to output more information, such as task inputs and target outputs.
- Faster builds - less overhead than a text log, can make builds significantly faster if other logs are disabled. They can be reconstructed later anyway if needed.
- Smaller disk size - a binary log is much smaller in size than a corresponding diagnostic-level text log (10-20x or more). This can result in significant storage savings on CI servers.
- Easier to read/analyze - text logs (especially from multi-processor builds) can become unwieldy, intertwined and hard to read. The viewer allows to collapse unneeded sections, as well as intelligent search.
- Programmatic access - All information is easily accessible programmatically for tools such as analyzers (whereas you need to parse text logs yourself and it's hard without a clearly defined structure) A .NET API is available to load and query binary logs.
- Embedded source files - optionally embed the source text of all project files and imported targets files used during the build, so it is possible to correlate log events with the source code. Preprocessed view (with all imports inlined) is available for each file (like /pp).
Read more about the new MSBuild binary log format (*.binlog)
Viewer Features
The MSBuild Structured Log Viewer can build projects and solutions or open existing log files:
Leverage the source code of projects and targets embedded in the log file:
The viewer supports two file formats:
- *.binlog (official MSBuild binary log format, produced by msbuild.exe /bl
- *.xml (for large human-readable XML logs)
The viewer can read all formats and can save to *.xml.
See here for the list of viewer features
Command-line help for the /bl switch
See MSBuild command-line help msbuild /? for more information on the /bl switch. The switch is available starting with MSBuild 15.3 (Visual Studio 2017 Update 3 or newer).
/binaryLogger[:[LogFile=]output.binlog[;ProjectImports={None,Embed,ZipFile}]]
Serializes all build events to a compressed binary file.
By default the file is in the current directory and named
"msbuild.binlog". The binary log is a detailed description
of the build process that can later be used to reconstruct
text logs and used by other analysis tools. A binary log
is usually 10-20x smaller than the most detailed text
diagnostic-level log, but it contains more information.
(Short form: /bl)
The binary logger by default collects the source text of
project files, including all imported projects and target
files encountered during the build. The optional
ProjectImports switch controls this behavior:
ProjectImports=None - Don't collect the project
imports.
ProjectImports=Embed - Embed project imports in the
log file.
ProjectImports=ZipFile - Save project files to
output.projectimports.zip
where output is the same name
as the binary log file name.
The default setting for ProjectImports is Embed.
Note: the logger does not collect non-MSBuild source files
such as .cs, .cpp etc.
A .binlog file can be "played back" by passing it to
msbuild.exe as an argument instead of a project/solution.
Other loggers will receive the information contained
in the log file as if the original build was happening.
You can read more about the binary log and its usages at:
https://aka.ms/msbuild/binlog
Examples:
/bl
/bl:output.binlog
/bl:output.binlog;ProjectImports=None
/bl:output.binlog;ProjectImports=ZipFile
/bl:..\..\custom.binlog
/binaryLogger
Recording a binary log with older versions of MSBuild
The built-in /bl switch was only introduced in MSBuild 15.3 (Visual Studio 2017 Update 3). However there is a way to record a binary log with previous versions of MSBuild as well. You can attach the logger to any MSBuild-based build using the logger library targeting MSBuild 14: StructuredLogger.dll. It is available in a NuGet package:
MSBuild.StructuredLogger.net45
Or you could download it directly here: https://msbuildlog.com/net45/StructuredLogger.dll
Use a command-line such as this to pass the BinaryLogger to MSBuild:
msbuild solution.sln /t:Rebuild /v:diag /noconlog /logger:BinaryLogger,StructuredLogger.dll;1.binlog
Investigating IDE and design-time builds inside Visual Studio
Use the Project System Tools Visual Studio extension to record binary logs of IDE and design-time builds.
See more information about design-time builds here:
https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md
Security Warning
The binary log contains and exposes all environment variables from the machine that the build ran on. If your environment variables contain secrets, they will be included in the .binlog file in plaintext.
Additionally, the source code of all project (.csproj) and targets files (.props, .targets, etc) is embedded in the .binlog file as well.
Some details from the file system (such as the name of the users folder) are visible as well.
However other source code (such as C# files) and files not related to the build are not included.
Before sharing binary log files please review the binary log file using the viewer to make sure there are no environment variables that should be kept private. Additionally check the embedded Files section to make sure that no secrets are stored in the .csproj files.
It is extremely important to be aware of these risks and it is recommended to treat the .binlog files like you treat your source code.
Reading MSBuild .binlogs programmatically
Reference the MSBuild.StructuredLogger NuGet package. All you need is to reference StructuredLogger.dll from that package.
You may also need to reference MSBuild Microsoft.Build.Framework.
There are various APIs for various scenarios. A high-level API to read a .binlog file into a tree structure that you normally see in the viewer is:
using System;
using Microsoft.Build.Logging.StructuredLogger;
class BinaryLogReadBuild
{
static void Main(string[] args)
{
string binLogFilePath = @"C:\temp\test.binlog";
var buildRoot = BinaryLog.ReadBuild(binLogFilePath);
buildRoot.VisitAllChildren<CscTask>(c => Console.WriteLine(c.CommandLineArguments));
}
}
There is a more formal API to read the C# compiler invocations from a binlog, read more here:
https://github.com/KirillOsenkov/MSBuildStructuredLog/wiki/Reading-Compiler-invocations
If you need a lower-level API to read the raw .binlog records yourself you can use BinLogReader.ReadRecords(string binLogFilePath):
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
using Microsoft.Build.Logging.StructuredLogger;
class BinLogReader
{
static void Main(string[] args)
{
string binLogFilePath = @"C:\temp\test.binlog";
var binLogReader = new BinLogReader();
foreach (var record in binLogReader.ReadRecords(binLogFilePath))
{
var buildEventArgs = record.Args;
// print command lines of all tool tasks such as Csc
if (buildEventArgs is TaskCommandLineEventArgs taskCommandLine)
{
Console.WriteLine(taskCommandLine.CommandLine);
}
}
}
}
Another example of using the API is reading start/end times and durations of targets:
https://github.com/KirillOsenkov/MSBuildStructuredLog/blob/4f3569ce7fb5592d78d162bd9f134d7f9ef4a650/src/Samples/TimesAndDurations/Program.cs#L23
Source code on GitHub
The MSBuild Structured Log Viewer project is open-source on GitHub at:
https://github.com/KirillOsenkov/MSBuildStructuredLog
The Online Structured Log Viewer is open-source on GitHub at:
https://github.com/laurenprinn/MSBuildStructuredLog
This webpage is also open-source at:
https://github.com/KirillOsenkov/MSBuildLog