Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info
iconfalse
titleTable of Contents

Table of Contents
maxLevel1

Below:

  • "Project" means one project of a solution defined by a ".csproj" file.
  • "Assembly" means a compiled project of a solution (dll or executable).

Requirements

Your .NET solution must be compiled if you want prior to use the following plugins:

  • FxCop
  • Gendarme
  • Gallio
  • NDeps

If your solution is not compiled (or if you do not want to use some of the external tools for your analysis), you can deactivate the external tools by adding the following properties to your configuration filethe SonarQube analysis. The SonarQube analysis must be run in the same directory where the solution was compiled.

By default, the C# plugin triggers the execution of some external tools. To deactivate some of them, you can set the below properties:

Code Block
languagebash
# External tools to deactivate when the solution is not compiled
sonar.fxcop.mode=skip
sonar.gendarme.mode=skip
sonar.gallio.mode=skip
sonar.ndeps.mode=skip

# Other external tools that you can deactivate
sonar.stylecop.mode=skip

Best Practices

...

Running an Analysis with the SonarQube Runner

  1. Compile your solution. SonarQube's primary goal is to

...

  1. analyze source code, so everything has been made to work seamlessly

...

  1. after the compilation of a solution

...

  1. . In other words, if you have a build

...

  1. process that

...

  1. moves the assemblies and packages your application, it is definitely best to run SonarQube before

...

  1. (or in a separate process)

...

Running an Analysis with the SonarQube Runner (Recommended Way)

  1. .

...


  1. Create a sonar-project.propetiesproperties file and place it in the same folder as the Solution solution file (.sln).
    Here is the simplest sonar-project.properties file that you can write to be able to run an analysis on your project:

    Code Block
    titlesonar-project.properties
    languagebash
    # Project identification
    sonar.projectKey=com.mycompany:myCSharpApplication
    sonar.projectVersion=1.0-SNAPSHOT
    sonar.projectName=My C#CSHARP Application
    
    # Info required for SonarQube
    sonar.sourceslanguage=.cs
    
     # AlwaysTo setprevent itany likeissues thatwhile asanalyzing thismultiple propertysolutions iscontaining not used
    sonar.language=cs
    
  2. Run the following command from your Solution folder:

    Code Block
    languagenone
    sonar-runner

 

Tip
titleFile location

The configuration file should be placed at the root of your Solution. This way, SonarQube will automatically discover the .sln file located in this folder.
If the Solution file is elsewhere, then you can set the sonar.dotnet.visualstudio.solution.file property to specify its relative path, but we do recommend you to follow our best-practices.

Running a SonarQube Analysis with Maven

If you are familiar with Maven, you can also use the maven-dotnet-plugin in order to compile and package .Net projects. If you already use a CI tool such as Jenkins on Java Maven projects, you can use the maven-dotnet-plugin to handle .Net projects the same way

The POM file

Simplest "pom.xml" file for Maven

Code Block
langxml
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany</groupId>
  <artifactId>myCSharpApplication</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>My C# Application</name>

  <properties>
	<sonar.language>cs</sonar.language>
  </properties>
  
  <build>
    <sourceDirectory>${basedir}</sourceDirectory>
  </build>
  
</project>

Above, a very simple pom.xml file that can be used instead of the sonar-project.properties of the SonarQube Runner. If you want to use maven compile and run the tests of your visual studio solution, you also need to declare the maven-dotnet-plugin. Please take a look at the examples provided on the maven-dotnet-plugin site.

The settings file

You need to configure somewhere the location of the external tools used by SonarQubesuch as FxCop, Gendarme or StyleCop. The C# plugins options pages describes the properties needed in the settings.xml. Below an xml fragment describing a maven profile you could add in your settings.xml file :

Code Block
langxml
   <profile>
      <id>dotnet</id>
      <activation>
        <!-- Optional activation by default -->
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
      
        <sonar.gallio.installDirectory>C:/Program Files/Gallio</sonar.gallio.installDirectory>
   
        <!-- Location of FxCop installation-->
        <sonar.fxcop.installDirectory>C:/Program Files/Microsoft FxCop 10.0</sonar.fxcop.installDirectory>

        <!-- Location of PartCover installation-->
        <sonar.partcover.installDirectory>C:/Program Files/PartCover/PartCover .NET 4.0</sonar.partcover.installDirectory>

        <!-- Location of Gendarme installation
        NOT MANDATORY
        <sonar.gendarme.installDirectory>C:/Program Files/gendarme-2.6-bin</sonar.gendarme.installDirectory>
        -->
        <!-- Location of StyleCop installation
        NOT MANDATORY 
        <sonar.stylecop.installDirectory>C:/Program Files/Microsoft StyleCop 4.3.2.1</sonar.stylecop.installDirectory>
        -->
      </properties>
   </profile>

You can also use property keys used by the maven dotnet plugin. Feel free to take a look at the examples on the maven dotnet plugins.

Run the analysis

Code Block
languagenone
mvn sonar:sonar

Paths and File Patterns

...

  1. projects with similar keys
    # Will be set by default to safe starting at version 2.2: http://jira.codehaus.org/browse/SONARDOTNT-339
    sonar.dotnet.key.generation.strategy=safe
     
    # This property is set because it is required by the SonarQube Runner.
    # But it is not taken into account because the location of the source
    # code is retrieved from the .sln and .csproj files.
    sonar.sources=.
    
    



  2. Run the following command from the directory containing the sonar-project.properties file (= the directory containing the solution):

    Code Block
    languagenone
    sonar-runner

A sample project is available on GitHub that can be browsed or downloaded: /projects/languages/csharp.

Path Patterns

Always use "/" instead of "\" (even if it looks weird on a Windows box).

When noted, Ant style wildcard patterns can be used. * means any file or any directory. ** means any directory directories and subdirectorysubdirectories:

Code Block
**/Foo*.dll

Above pattern will select any dll files prefixed by Foo anywhere in a project.
You can combine an absolute path prefix with wildcards:

Code Block
T:/lib/**/*.dll

This will select any dll files in any subfolder of the lib folder of the drive T.

If you need to reference assembly files outside your solution folder, you can use absolute paths or ../. For example:

Code Block
$(SolutionDir)/../lib/**.*dll

Above pattern can be used to specify all the dll files of a lib folder located at the same level as the root folder of your visual studio solution.

...

languagebash
# Relative path that refers to any dll files prefixed by Foo in the solution
**/Foo*.dll

# Absolute path that refers to any dll files in any sub-directories of the lib directory of the drive T
T:/lib/**/*.dll

 

In some advanced use cases (which should not occur too often if you follow our best practices), the following placeholders can be used in path patterns:

ExpressionDescription
$(SolutionDir)Root directory of the solution, this is the directory where the ".sln" file is located.
$(ProjectName)Name of the currently analysed analyzed project of the solution.
$(AssemblyName)Name of the assembly generated by the currently analysed analyzed solution. Works only for non asp -ASP projects.
$(AssemblyVersion)Version of the assembly generated by the currently analysed analyzed solution.
$(OutputType)Type of the generated assembly. Can be "dll" or "exe".
$(RootNamespace)Root namespace of the currently analysed analyzed project.

So if the solution you need to analyze use a "post compilation" msbuild/nant task that copies the generated assemblies somewhere into a "BUILD" directory, you can set the sonar.dotnet.assemblies property with this patternFor example:

Code Block
languagebash
$(SolutionDir)/../lib/**.*dll
$(SolutionDir)/BUILD/**/$(AssemblyName).$(OutputType)

Tools such as Gendarme and FxCop will be executed once for each project of the solution. For each project, the expressions "AssemblyName" and "OutputType" will be evaluated in order to locate the project assembly.

Unit Tests and Code Coverage

There are two different ways to feed the SonarQube platform with information on unit tests execution and code coverage:

  • Letting the SonarQube platform drive the execution of the unit tests and the code coverage tool
  • Reusing reports that have been generated by external tools prior to the SonarQube analysis

Those two ways are handled by Gallio. So you first have to install it on the machine(s) running the SonarQube analysis. You also have to install the code coverage tool of your choice that will be driven by Gallio. Supported tools are dotCover, NCover, OpenCover and PartCover.

Configuring Gallio

...

Note
titleAvoid too much complex configuration of paths

If you start using absolute paths or placeholders in path patterns, this means that your configuration becomes more complex and you are likely to face issues sooner or later. Everything has been done to make sure you need to write as few configuration lines as possible.

Advanced Usage

Setting the .NET SDK to use

To set the default version of the .NET SDK to be used, log in as a System administrator and go to Settings > Configuration > General Settings > .NET Gallio.

...

and set the sonar.

...

dotnet.

...

version property.

...

Letting the SonarQube platform drive the execution of the unit tests and the code coverage tool

This is the default mode.

The first and unique step is to tell SonarQube which assemblies are unit test assemblies. To do so, set the sonar.donet.visualstudio.testProjectPattern property.Note that you can override this default value in your analysis configuration file.

The same parametrization is available for the Silverlight Framework: sonar.silverlight.version property.

Setting exclusions

By default, generated code is excluded from the analysis (Reference.cs or *.designer.cs files): sonar.dotnet.excludeGeneratedCode is set to true.

To exclude projects, use the sonar.skippedModules property. It is a comma-separated list of project names. The names that must be used are the identifiers in the solution file: the first string right after the equals sign on a project definition.
Known limitation: this property does not currently work while the "sonar.dotnet.key.generation.strategy" is set to "safe". See SONARDOTNT-10.

Code Block
languagebash
# Semicolon-separatedTo list of patterns to identify unit test assemblies
# Default value is *.Tests
sonar.donet.visualstudio.testProjectPattern=*.Tests;*.UnitTests

Then, you just have to run a SonarQube analysis and you'll get data on unit tests and code coverage. Indeed, the paths to the compiled unit test assemblies are automatically retrieved from the Visual Studio "csproj" files. And the execution of unit tests and the driving of the coverage tool is automatically performed by Gallio.

Reusing existing reports

To activate this mode, add the following line to your project configuration file:

Code Block
languagenone
sonar.gallio.mode=reuseReport

...

exclude "FooProject":

# ...
# Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "FooProject", "FooProject", "{59BECB8B-A7E3-4823-9CE6-584D0D1755EE}"
# ...

sonar.skippedModules=FooProject

To exclude files, see Project Administration.

On some specific components, you can also prevent issues from being raised against a set of coding rules: see the Switch Off Violations plugin.

Detecting issues with external tools

See FxCop, Gendarme and StyleCop.

Unit tests, integration tests and code coverage

See Unit Tests, Integration Tests and Code Coverage.

Architecture check

See NDeps plugin.

FAQ

Analysis succeeds but too few issues are found

Some tools like FxCop or Gendarme require assemblies. Having too few issues most often comes from the following reasons:

  • The solution has not been compiled prior to the SonarQube analysis
  • The solution has been compiled but the corresponding assemblies have been moved somewhere else (because of a specific build process) and SonarQube cannot find them
  • The solution has been compiled (and the assemblies have not been moved). But the whole solution folder has been moved to another location (and therefore the debug PDB files no longer point to the original source locations)

I cannot place the analysis configuration file in the directory containing my solution

Before following this workaround, make sure that you've got strong reasons not to put the analysis configuration file into the folder containing the solution. Note that this workaround may lead to further tricky configuration and issues.

Code Block
languagebash
# PathRelative topath from the unitanalysis testsconfiguration executionfile report
sonar.gallio.reports.path=

# Path to the code coverage report
sonar.gallio.coverage.reports.path=

# Paths can be absolute or relative to the Solution base directory

Deactivating Unit Tests and Code Coverage

Add the following line to your project configuration file:

Code Block
languagenone
sonar.gallio.mode=skip

FAQ

My unit tests and integration tests are defined within the same assemblies, how can I run my unit tests only?

Define the sonar.gallio.filter property:

Code Block
languagebash
# To run test from the "unit" category only
sonar.gallio.filter=CategoryName:unit

How can I exclude some specific assemblies and/or namespaces from code coverage computation?

Define the sonar.gallio.coverage.excludes property:

Code Block
languagebash
# Comma-separated list of namespaces and assemblies excluded
??? To completely be reviewed and completed ???

# PartCover format: [assembly]namespace ??? Same format for OpenCover ???
sonar.gallio.coverage.excludes=[Example.Tests]

# NCover format: name of the assemblies to exclude ??? Can namespaces be excluded as well ???
sonar.gallio.coverage.excludes=Example.Tests,Fake.Tests

# dotCover filter format: -:module=ASSEMBLY;class=*;function=*;
sonar.gallio.coverage.excludes=

SonarQube cannot retrieve the compiled unit test assemblies

If for some reasons, compiled unit test assemblies are moved after the build (no longer available in directories defined in "csproj" files), you can tell SonarQube where to find them thanks to the sonar.dotnet.test.assemblies property.

Code Block
languagebash
# Comma-separated list of paths to the compiled unit test assemblies
# Paths can be absolute to the Solution base directory
sonar.dotnet.test.assemblies=C:/myProject/testAssemblies

# Ant-like patterns can also be used
sonar.dotnet.test.assemblies=$(SolutionDir)/../myAssemblies/**

How to define the Gallio runner type?

Set the sonar.gallio.runner property. As describe in the Gallio documentation, possible values are IsolatedAppDomain (PartCover default runner type), IsolatedProcess and Local.

Does not apply to NCover.

NCover, the analysis succeeded but only one test assembly is taken into account

The NCover Complete Edition allows to run tests from multiple assemblies and merge the coverage data, the NCover Classic Edition does not.

The workaround is to activate the Gallio safe mode (sonar.gallio.safe.mode=true). Gallio will then be launched for each test assembly and the generated XML reports will be merged.

How to set Gallio's timeout?

Set the sonar.gallio.timeoutMinutes property (default value is 30).

How can I run Gallio and PartCover on a 64-bits Windows?

Gallio and PartCover work perfectly out-of-the-box on x86 Windows, but not on 64-bit versions. To make them work:

  1. Download the latest Gallio x64 installer and install it in a folder, but not under "Program Files".
  2. Download the latest PartCover installer and install it in a folder, but not under "Program Files".
  3. Run corflags.exe on Gallio and PartCover executables:

    Code Block
    languagebash
    # Go to the PartCover folder
    corflags /32bit+ /force PartCover.exe
    corflags /32bit+ /force PartCover.Browser.exe
    
    # Go to the Gallio bin folder
    corflags /32bit+ /force Gallio.Echo.exe
    

See http://www.planetgeek.ch/2009/10/15/get-partcover-running-on-x64-windows/

Integration Tests and Code Coverage

As the principles are very similar to the unit tests. please read the Unit Tests and Code Coverage before.

Letting the SonarQube platform drive the execution of the unit tests and the code coverage tool

To activate this mode, add the following line to your project configuration file:

Code Block
languagenone
sonar.gallio.it.mode=active

The first and unique step is to tell SonarQube which assemblies are integration test assemblies. To do so, set the sonar.donet.visualstudio.itProjectPattern property.

Code Block
languagebash
# Semicolon-separated list of patterns to identify integration test assemblies
sonar.donet.visualstudio.itProjectPattern=*.Integration.Tests;*.IntegrationTests

Then, you just have to run a SonarQube analysis and you'll get data on integration tests and code coverage. Indeed, the paths to the compiled integration test assemblies are automatically retrieved from the Visual Studio "csproj" files. And the execution of integration tests and the driving of the coverage tool is automatically performed by Gallio.

Reusing existing reports

To activate this mode, add the following line to your project configuration file:

Code Block
languagenone
sonar.gallio.it.mode=reuseReport

Then, you just need to provide SonarQube with the following reports: integration tests execution report and code coverage report.

Code Block
languagebash
# Path to the integration tests execution report
sonar.gallio.it.reports.path=

# Path to the code coverage report
sonar.gallio.it.coverage.reports.path=

# Paths can be absolute or relative to the Solution base directory

Deactivating Integration Tests and Code Coverage

This is the default mode.

FAQ

See Unit Tests and Code Coverage > FAQ.

Corresponding integration test properties are:

...

to the folder containing the solution
sonar.dotnet.visualstudio.solution.file=my_solution_directory/solution_file.sln

Anchor
assemblies
assemblies
SonarQube cannot retrieve the assemblies

The configuration defined to build the solution will be used to locate the assemblies during the SonarQube analysis. Two properties are taken into account:

  • sonar.dotnet.buildConfiguration property (default value is Debug)
  • sonar.dotnet.buildPlatform property (default value is AnyCPU)

Let's take the folowing example:

Code Block
title".csproj" file
languagehtml/xml
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>  <!-- SonarQube will try to retrieve the assembly from this folder -->
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>  <!-- SonarQube will try to retrieve the assembly from this folder -->
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  ...

If you use the default configuration (Debug|AnyCPU), SonarQube will try to retrieve the assembly of this project in <project_directory>/bin/Debug.

If you set the properties to:

Code Block
languagebash
sonar.dotnet.buildConfiguration=Release
sonar.dotnet.buildPlatform=AnyCPU

SonarQube will try to retrieve the assembly of this project in <project_directory>/bin/Release.

Depending on when you run SonarQube in your continuous integration process, it is very important to properly set those properties. A proper configuration will allow SonarQube to automatically retrieve the assemblies and smoothly perform the analysis. It is highly recommend that you run SonarQube right after the compilation phase.

For example, if you run SonarQube after the packaging phase that moves all the assemblies into a single directory, you will face over-complicated configuration because you will have to tell SonarQube where to find the assembly for each project. To do so, set the sonar.dotnet.assemblies property. It is a path pattern that will be used to find the assembly of the analyzed project. The path pattern can be absolute or relative to the directory containing the ".csproj" file.

Code Block
languagebash
# If, for each project, the assembly is moved to a "bin/package" directory inside the project directory
sonar.dotnet.assemblies=bin/package/$(AssemblyName).$(OutputType)
 
# If all the assemblies are copied into a "package" directory located in the solution directory
sonar.dotnet.assemblies=$(SolutionDir)/package/$(AssemblyName).$(OutputType)

SonarQube C# parser known limitations

How can I integrate SonarQube in my existing TFS Build environment processes?

Most people want to add SonarQube as an additional step in existing processes, which usually brings a lot of troubles because those processes manipulate assemblies - whereas the SonarQube C# plugins rely best on information found in the source files (mostly "csproj" files).

Generally speaking, it's better / easier to set up a separate Continuous Inspection process that only:

  1. Compiles the solution
  2. Runs a SonarQube analysis

in order to keep the SonarQube-related configuration as simple as possible.

You can read this thread to see how this has been achieved by C# plugin users.

Why do I get MSBuild error such as "error MSB4126: The specified solution configuration "Debug|HPD" is invalid"?

You are using a 64-bit windows OS. There is an environment variable "Platform=HPD" that makes msbuild fail. Try to run:

Code Block
set platform=[enter]
sonar-runner

On Windows 7 I get "The Silverlight 3/4 SDK is not installed" error message

64-bit msbuild cannot be used with Silverlight. Check that you are not using a 64-bit msbuild by taking a look at dotnet.3.5.sdk.directory properties. "Framework64" should not be present in the path.

The analysis fails with an OutOfMemory exception

The Java process performing the analysis might need more memory. Use the "-Xmx" option to specify the amount of memory that can be used. See the SonarQube Runner documentation for more details