Analyzing Visual Studio / MSBuild / .NET Core projects from the command line using PVS-Studio

This document covers the usage of command-line utilities for the analysis of MSBuild projects (.vcxproj / .csproj) and Visual Studio solutions.

This document covers the usage of command line utilities. Usage of plugins for Visual Studio and JetBrains Rider is described in the following documentation sections: "Getting acquainted with the PVS-Studio static code analyzer on Windows", "Using PVS-Studio with JetBrains Rider".

The command-line analyzer of MSBuild projects has various names on different platforms supported by the analyzer:

  • PVS-Studio_Cmd (analysis of solutions, C#, C++ projects on Windows);
  • pvs-studio-dotnet (analysis of solutions, C# projects on Linux / macOS);

The features described below are relevant for both utilities. Examples with PVS-Studio_Cmd / pvs-studio-dotnet are interchangeable unless explicitly stated otherwise.

Note. To analyze C++ projects that don't use the MSBuild build system, on Windows use the compilation monitoring system or direct integration of the analyzer into the build system. Analysis of C++ projects on Linux / macOS is described in detail in this section of the documentation.

Running analysis of sln and csproj/vcxproj files

Command line utilities are unpacked to the following directories by default:

  • PVS-Studio_Cmd.exe
    • Windows: "C:\Program Files (x86)\PVS-Studio\";
  • pvs-studio-dotnet
    • Linux: "/usr/share/pvs-studio-dotnet/";
    • macOS: "/usr/local/share/pvs-studio-dotnet".

'--help' command displays all available arguments of the analyzer:

PVS-Studio_Cmd.exe --help

Let's look at the main arguments of the analyzer:

  • --target (-t): required parameter. Allows you to specify the object to be tested (sln or csproj/vcxproj file);
  • --output (-o): path to the file, where the analysis results will be written. If this parameter is omitted, the analyzer report file will be created next to the file specified using the '--target' flag. The analyzer report can be saved in 2 formats: .json and. plog. The format type is determined by the specified extension. By default, a report in the .plog format will be created without specifying this flag;
  • --platform (-p) and --configuration (-c): the check will be run for the specified platform and configuration. If these parameters are not specified, the first available "platform|configuration" (when checking the sln file) pair will be selected or "Debug|AnyCPU" (when checking a separate csproj project) or "Debug|Win32" (when checking a separate vcxproj project);
  • --sourceFiles (-f): path to the text file containing a list of paths to source files for the analysis (each must be on a separate line). Relative and absolute paths are supported. In this mode, when analyzing C and C++ files, a compilation dependency cache is generated, the location of which can be controlled using the '-D' flag;
  • --dependencyRoot (-D): an optional path to the directory where the source file dependency caches are located. Works in addition to the '--sourceFiles' (-f) flag;
  • --dependencyCacheSourcesRoot (-R): an optional path to specify the root directory of relative source file paths in dependency caches generated with '--sourceFiles' (-f) flag;
  • --settings (-s): path to the PVS-Studio configuration file. If this parameter is omitted, the Settings.xml file will be used, located in the directory "C:\Users\%UserName%\AppData\Roaming\PVS-Studio\" on Windows or "~/.config/PVS-Studio/" on Linux / macOS. These same settings files are used by plugins (Visual Studio, Rider), which makes it possible to edit them using the PVS-Studio plugin interface in these IDEs. Please note that for the analyzer to work under Windows, the settings file must contain registration information. Various ways to enter a license are described here. Depending on the settings file used, the following rules apply:
    • when using the default settings file it must contain registration information;
    • if you explicitly specify the path to the settings file, the registration information must be written either in the specified settings file or in the default settings file;
  • --suppressAll (-a): add unsuppressed warnings in suppress files of corresponding projects (disabled by default). If this flag is present, all messages will be added to the suppress warnings base after saving the check result. The flag supports 2 operating modes.
    • SuppressOnly adds messages from the passed analyzer report to the suppress files without running the analysis;
    • AnalyzeAndSuppress runs the analysis, saves the analyzer report, and only after this suppresses the messages found in it. This mode allows you to get a report from the analyzer on regular runs, which contains only new messages for the changed \ written code, i.e. new messages get into the new log and get immediately suppressed - they won't be issued during the subsequent check. However, if you still need to view the old messages (without rechecking), a file with the full check report (only for .plog analyzer reports) will be saved next to the analyzer report containing new messages. Read more about message suppression mode in this section of the documentation;
  • --sourceTreeRoot (-e): the root part of the path that PVS-Studio will use when generating relative paths in diagnostic messages. Setting this parameter overrides the 'SourceTreeRoot' value in the PVS-Studio settings;
  • --incremental (-i): incremental analysis mode. For more information about incremental analysis in PVS-Studio, see the section "PVS-Studio incremental analysis mode". There are following modes of incremental analysis available:
    • Scan - analyze all dependencies to determine, which files will be analyzed incrementally. The analysis itself won't be performed. Changes made since the last build will be taken into account, and the previous history of changes will be deleted.
    • AppendScan - analyze all dependencies to determine, which files will be analyzed incrementally. The analysis itself won't be performed. Changes made since the last build, as well as all previous changes, will be taken into account.
    • Analyze - perform incremental analysis. This step should be done after Scan or AppendScan and can be performed both before and after the build of a solution or project. Static analysis will only be performed for files from the list obtained by executing the Scan or AppendScan commands.
    • ScanAndAnalyze - analyze all the dependencies to determine which files should be analyzed incrementally and perform incremental analysis of the edited files with the source code. Changes made since the last build will be taken into account.
  • --msBuildProperties (-m): allows you to set or redefine project level properties. To set or redefine multiple project level properties, use the "|" symbol, for example: --msBuildProperties WarningLevel=2|OutDir=bin\OUT32\
  • --excludeDefines (-x): a list of symbols that will be excluded from the current set when analyzing the project. If you need to list several symbols, use ';' as the delimiter. Example: --excludeDefines "DEF1;DEF2". This option is only taken into account when analyzing C# projects.
  • --appendDefines (-d): a list of symbols that will be added to the current set when analyzing the project. If you need to list several symbols, use ';' as the delimiter. Example: --appendDefines "DEF1;DEF2". This option is only taken into account when analyzing C# projects.
  • --selectProjects (-S): a list of analyzed solution's projects (sln) to be analyzed. Other projects will be excluded from the analysis. It supports listing projects using the name of the project file (with or without an extension), using an absolute or relative path. If you need to list multiple projects, use ';' as the delimiter. Example: --selectProjects Project1;"Project 2.vcxproj";".\Project3\Project3.csproj".
  • --excludeProjects (-E): a list of projects in the analyzed solution (sln) that will be excluded from the analysis. It supports listing projects using the name of the project file (with or without an extension), using an absolute or relative path. If you need to list multiple projects, use ';' as the delimiter. Example: --excludeProjects Project1;"Project 2.vcxproj";".\Project3\Project3.csproj".
  • --rulesConfig (-C): path to the .pvsconfig diagnostics configuration file. It can be used together with configuration files from projects / solutions and configuration files from directories:
    • Windows: "%AppData%\PVS-Studio\";
    • Linux / macOS: "~/.config/PVS-Studio/".

Here is an example of running a check of the files list written in "pvs.txt", from the solution "My Solution":

PVS-Studio_Cmd.exe --target "mysolution.sln" --platform "Any CPU" 
--configuration "Release" --output "mylog.plog"
--sourceFiles "pvs.txt" --progress

PVS-Studio command-line version supports all settings on filtering/disabling messages available in the IDE plugin for Visual Studio. You can either set them manually in the xml file, passed through the '--settings' argument, or use the settings specified through the UI plugin, without passing this argument. Note that the PVS-Studio IDE plugin uses an individual set of settings for each user in the system.

Only relevant for PVS-Studio_Cmd. If you have installed multiple instances of PVS-Studio of different versions for the current system user, all instances of the program will use the installation directory specified during the last installation. To avoid conflicts in the analyzer's operation, in the settings passed with the --settings (-s) argument, the path to the installation directory (the value of the <InstallDir> element) must be specified.

Specification of individual files for analysis

PVS-Studio_Cmd allows you to selectively check individual files specified in the list passed using the '--sourceFiles' (-f) flag. The file list is a simple text file that contains line-by-line paths to the files being checked. Relative file paths will be expanded relative to the current working directory. You can specify both compiled source files (c/cpp for C++ and cs for C#), and header files (h/hpp for C++).

In this mode, when analyzing C and C++ files, a compilation dependency cache is generated, which will be used for subsequent analysis runs. By default, dependency caches are saved in a special '.PVS-Studio' subdirectory where project files (.vcxproj) are located. If necessary, you can change their storage location using the '--dependencyRoot' (-D) flag. By default, dependency caches keep full paths to source files, and relocation of project files will cause caches' regeneration. You can generate portable caches by specifying the '--dependencyCacheSourcesRoot' (-R) flag, which will cause the source file paths inside caches to be generated relative to it.

Wildcard filtration of the analyzed

To specify the list of analyzed files with path patterns, you need to pass a specially formatted XML file to the '--sourceFiles' (-f) flag. It accepts the list of absolute and relative paths and/or wildcards to analyzed files.

<SourceFilesFilters>
  <SourceFiles>
    <Path>C:\Projects\Project1\source1.cpp</Path>
    <Path>\Project2\*</Path>
    <Path>source_*.cpp</Path>
  </SourceFiles>
  <SourcesRoot>C:\Projects\</SourcesRoot>
</SourceFilesFilters>

Command-line tools exit codes

The PVS-Studio_Cmd / pvs-studio-dotnet utilities have several non-zero exit codes that don't indicate a problem with the utility itself, i.e. even if the utility returned not '0', it doesn't mean that it crashed. The exit code is a bit mask that masks all possible states that occurred during the operation of the utility. For example, the utility will return a non-zero code if the analyzer finds potential errors in the code being checked. This allows you to handle this situation separately, for example, on the build server, when the analyzer usage policy doesn't imply the presence of warnings in the code uploaded in the version control system.

PVS-Studio_Cmd exit codes (Windows)

Let's look at all possible utility state codes that form the bit mask of the return code.

  • '0' - the analysis was completed successfully, no errors were found in the code being checked;
  • '1' - an error (crash) of the analyzer when checking one of the files;
  • '2' - a general (non-specific) error during the analyzer operation, intercepted exception during operation. This usually signals the presence of an error in the analyzer code itself and is followed by this error's stack trace in stderr. If you stumbled upon such an error, please, help us make the analyzer better and send this stack trace to us;
  • '4' - some of the passed command-line arguments are incorrect;
  • '8' - the specified project, solution, or analyzer settings file wasn't found;
  • '16' - the specified configuration and / or platform weren't found in the solution file;
  • '32' - the solution or project file isn't supported or contains errors;
  • '64' - invalid extension of the solution or project being checked;
  • '128' - invalid or expired analyzer license;
  • '256' - potential errors were found in the code being checked;
  • '512' - an error occurred while performing message suppression
  • '1024' - indicates that the analyzer license will expire within a month;

Here is an example of a Windows batch script for decrypting the return code of the PVS-Studio_Cmd utility:

@echo off

"C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe"
-t "YourSolution.sln" -o "YourSolution.plog"

set /A FilesFail = "(%errorlevel% & 1) / 1"
set /A GeneralExeption = "(%errorlevel% & 2) / 2"
set /A IncorrectArguments = "(%errorlevel% & 4) / 4"
set /A FileNotFound = "(%errorlevel% & 8) / 8"
set /A IncorrectCfg = "(%errorlevel% & 16) / 16"
set /A InvalidSolution = "(%errorlevel% & 32) / 32"
set /A IncorrectExtension = "(%errorlevel% & 64) / 64"
set /A IncorrectLicense = "(%errorlevel% & 128) / 128"
set /A AnalysisDiff = "(%errorlevel% & 256) / 256"
set /A SuppressFail = "(%errorlevel% & 512) / 512"
set /A LicenseRenewal = "(%errorlevel% & 1024) / 1024"

if %FilesFail% == 1 echo FilesFail
if %GeneralExeption% == 1 echo GeneralExeption
if %IncorrectArguments% == 1 echo IncorrectArguments
if %FileNotFound% == 1 echo FileNotFound
if %IncorrectCfg% == 1 echo IncorrectConfiguration
if %InvalidSolution% == 1 echo IncorrectCfg
if %IncorrectExtension% == 1 echo IncorrectExtension
if %IncorrectLicense% == 1 echo IncorrectLicense
if %AnalysisDiff% == 1 echo AnalysisDiff
if %SuppressFail% == 1 echo SuppressFail
if %LicenseRenewal% == 1 echo LicenseRenewal

pvs-studio-dotnet exit codes (Linux / macOS)

Note. Since the maximum value of the exit code under Unix is limited by 255, exit codes of the PVS-Studio_Cmd (where the exit code may exceed 255) and pvs-studio-dotnet utilities are different.

Let's look at all possible utility state codes that form the bit mask of the return code.

  • '0' - analysis was successfully completed, no issues were found in the source code;
  • '1' - incorrect or out-of-date analyzer license;
  • '2' - general error in the analyzer's operation. This includes missed command-line arguments, invalid solution or project specified for analysis, an error inside the analyzer, etc. If an error message is followed by a stack trace, please help us improve the analyzer by sending it to us;
  • '4' - indicates that the analyzer license will expire within a month;
  • '8' - some issues were found in the source code;

Analysis run from the command line for C/C++ projects that don't use the Visual Studio build system

Note. This section is relevant for Windows. Analysis of C++ projects on Linux / macOS is described in the corresponding section of the documentation.

If your C/C++ project doesn't use standard Visual Studio build systems (VCBuild/MSBuild) or even uses your own build system / make files via NMAKE Visual Studio projects, you will not be able to check such a project using PVS-Studio_Cmd.

In this case, you can use the compiler monitoring system, which allows you to analyze projects regardless of their build system, "intercepting" the start of compilation processes. The compilation monitoring system can be used either from the command line or through the user interface of the C and C++ Compiler Monitoring UI application.

You can also directly embed the command line launch of the analyzer core right into your build system. Mind you, this will require writing a call to the PVS-Studio analyzer.exe core for each compiled file, similar to the the way how the C++ compiler is called.

Effect of PVS-Studio settings on command line run; filtering and converting analysis results (plog\json file)

When you run code analysis from the command line, the default settings are the same as when you run analysis from the IDE (Visual Studio / Rider). You can also specify which settings file to use via the --settings argument, as described above.

For example, as for the filter system (Keyword Message Filtering and Detectable Errors), it is NOT used when analyzing from the command line. Which means that the report file will contain all error messages regardless of the parameters you set. However, when you upload the results file to the IDE, the filters will already be applied. This is because filters are applied dynamically to results. The same occurs when running from the IDE as well. This is very convenient, because when you get a list of messages, you may want to disable some of them (for example, V201). Just disable them in the settings and the corresponding messages will disappear from the list WITHOUT restarting the analysis.

The analyzer report format isn't intended for direct display or human reading. However, if you need to filter the analysis results in some way and convert them to a "readable" view, you can use the PlogConverter utility distributed with PVS-Studio.

To work with reports in different formats, you need to use different utilities:

  • .plog – PlogConverter.exe (available only on Windows);
  • .json – plog-converter (Linux, macOS).

The source code of both utilities is open and available for download: PlogConverter; plog-converter, which allows you to simply add support for new formats based on existing algorithms.

These utilities are described in more detail in the corresponding sections of the documentation:


Bugs Found

Checked Projects
409
Collected Errors
14 072
This website uses cookies and other technology to provide you a more personalized experience. By continuing the view of our web-pages you accept the terms of using these files. If you don't want your personal data to be processed, please, leave this site. Learn More →
Accept