Using FxCop: A Short Tutorial

This section describes how to get up and running quickly with FxCop. While this is not the main focus of this document, new FxCop users may find it helpful. For additional resources on using the program, refer to FxCop's official documentation.

Recall that FxCop checks compiled assemblies. Prior to running FxCop, you need to compile the program that you want to check. FxCop supports assemblies written in C#, VB.NET, C++/CLI, and other managed .NET languages. This is the result of FxCop directly checking assemblies instead of source code files. It is best to do a Debug build of your application and be sure that you generate the program database (PDB) files. These are the defaults for builds performed using Visual Studio. The program database files will supply FxCop with the debugging information it needs to trace problems back to line numbers in your source code.

Once you have compiled your program, start FxCop. FxCop initially displays a blank project to which you can add one or more assemblies and choose which rules you want to enforce. Click the Project, Add Targets menu item to add your assembly (EXE or DLL) to the FxCop project. If your Visual Studio solution consists of several projects, you might want to add other assemblies at this time as well.

Next, you will probably want to shut off rule checking against automatically generated code. Examples of generated code include the designer parts of classes generated by the Visual Studio Form and DataSet designers. Such code violates some rules in minor ways. Since generated code is typically not modifiable, these violations are usually just noise. You can turn off checking generated code through the Project, Options menu item. Click the Spelling & Analysis tab and check the box for Suppress analysis results against generated code.

If you want to configure which rules are enabled, you can do so on the Rules tab in the main window. By default, all of the rules that ship with FxCop are enabled. Once you are finished configuring FxCop, you are ready to run it. Click the Analyze button on the toolbar. FxCop will check the chosen assemblies against the chosen rules and output a report of any violations that were found.

Figure 1. FxCop Sample Screenshot

FxCop Sample Screenshot

By clicking on a violation in the report, you can obtain detailed information about that violation. You may decide to:

  1. Modify your source code to fix the violation. If possible, FxCop displays a hyperlink to your Visual Studio source file to assist you in locating the code that needs to be modified.

  2. Enter an exclusion, which declares an exception to the rule. You can do this using the FxCop GUI which will record this in the FxCop project file. A better way is to use the SuppressMessageAttribute in your source code file as described below.

  3. Ignore the violation for now. You can come back to it at a later time.

Although the FxCop GUI provides a way to record exclusions in the FxCop project file, a superior mechanism for declaring exceptions to rules is to use the SuppressMessageAttribute which comes with .NET in the System.Diagnostics.CodeAnalysis namespace. To use it, make note of the Category name (here, Microsoft.Usage) and the CheckId (here, CA2201) as displayed by FxCop.

[Tip]Tip

You may find it a useful technique to temporarily mark exclusions using the FxCop GUI and later, at your convenience, replace them with SuppressMessageAttribute in your source code.

For C# code:

using System.Diagnostics.CodeAnalysis;

[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
public void YourMethod()
{
     .
     .
     .
}

For VB.NET code:

Imports System.Diagnostics.CodeAnalysis

<SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")> _
Public Sub YourMethod()
{
     .
     .
     .
}

FxCop can automatically generate the correct SuppressMessageAttribute for you. Right-click on the problem in the FxCop GUI and choose Copy As, SuppressMessage. This will place the code declaring the SuppressMessageAttribute on the clipboard. If you are using C#, it will be exactly what you need. If you are using VB.NET, you will need to make some slight modifications by hand to convert it from C# to VB.NET. Usually, this involves changing the square brackets to angle brackets. Sometimes, you will also need to change = to := if additional properties such as MessageId are included.

Generally, the SuppressMessageAttribute needs to be placed right before the declaration for the member identified in the Item column in the FxCop GUI. Usually, this will be a class or a method. There are some cases where placing the attribute in the correct location may be inconvenient or impractical. For instance, the member may be declared in a code file that was automatically generated by a tool, such as Visual Studio or a custom standalone utility. You can consider setting the option described earlier to instruct FxCop to not check the generated code. Nonetheless, your code generator might not mark its output with a System.CodeDom.Compiler.GeneratedCodeAttribute and, as a result, it might be incompatible with this exclusion option. A second case is the individual fields that implement Control members in the Windows Forms designer because these are not considered to be generated code. A third case is problems are associated with the module itself instead of a specific member. In all of these cases you can tell FxCop to generate a suppression for the problem that you can place at the module-level.

A module-level suppression means that the SuppressMessageAttribute is placed at the module-level in your code, prefixed by module:. The name "module-level" can be confusing; such a suppression does not have global effects. Just like ordinary SuppressMessageAttribute declarations, a single problem instance is suppressed. You specify the Scope and Target properties (and potentially a MessageId) to identify the precise problem to suppress. To automatically generate a module-level SuppressMessageAttribute, right-click on the problem and choose Copy As, Module-level SuppressMessage.

The following accomplishes the same suppression as the previous example using a module-level SuppressMessageAttribute in C#:

using System.Diagnostics.CodeAnalysis;

[module: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes",
  Scope="member",
  Target="TestProject.Form1.#YourMethod()")]

Equivalently, in VB.NET:

Imports System.Diagnostics.CodeAnalysis

<Module: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", _
  Scope:="member", _
  Target:="TestProject.Form1.#YourMethod()")> 

Module-level SuppressMessageAttribute declarations must come before most other code elements in a source file. In particular, it must come before namespace and class blocks.

[Tip]Tip

You might choose to put all of your module-level SuppressMessageAttribute declarations in their own, separate source file. For example, a SuppressMessages.cs file. Optionally, you might decide that you want to always use module-level suppressions. In this case, you would be able to put all of your suppressions for the assembly in the same source file.

In order for the SuppressMessageAttribute declarations to take effect, you need to declare the CODE_ANALYSIS custom constant in your Visual Studio project's properties under Advanced Compile Options.

Figure 2. Custom Constant for SuppressMessageAttribute

Custom Constant for SuppressMessageAttribute

FxCop 1.36 includes documentation that describes the FxCop user interface (and the command line interface as well) in detail. The documentation includes detailed information describing the reasoning behind all of the predefined rules and advice on modifying your code to resolve violations of them. This help is available within the program and online at http://msdn2.microsoft.com/en-us/library/bb429476.aspx.