Monday, February 15, 2010

Integrating FxCop into Visual Studio

At my previous company we had Visual Studio Team System (VSTS) which has Code Analysis (FxCop) integrated into Visual Studio. To turn it on one enters project properties and clicks on the Code Analysis tab. Each rule or group of rules is turned on by checking a box and the rules execute on every build of the project. I love FxCop because it teaches me how to be a better programmer, finds issues in my code, and makes my APIs more user friendly. I was disappointed upon discovering Code Analysis is a VSTS feature.

This post shows two options for getting FxCop 1.36 running on a each Visual Studio 2008 build without maintaining an FxCop project separate from a C# project.  On the downside it will run the same set of rules for each project, which works for my scenario but may pose problems when working with legacy code and new development because the legacy code will probably violate many rules.

This instructions assume the following environment:
  • MSbuild Version 3.5.30729.4926
  • 64 bit Windows (otherwise you will need to modify the C:\Program Files (x86) paths )
  • Visual Studio 2008
  • FxCop 1.36
Option #1: Integrating FxCop at the project level.
  1. Install FxCop
  2. Create a file: C:\Program Files (x86)\MSBuild\v3.5\FxCop.targets with the following text:
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <!-- Add FxCop to the list of targets to build -->
        <BuildDependsOn>$(BuildDependsOn);FxCop</BuildDependsOn>
      </PropertyGroup>
      <!-- Define the FxCop target we added above.-->
      <Target Name="FxCop">
        <Message Text="$(MSBuildToolsPath)" />
        <!-- The Condition attribute allows others to use the same project file without breaking their build when FxCop is not installed-->
        <Exec Command="&quot;$(ProgramFiles)\Microsoft FxCop 1.36\FxCopCmd.exe&quot; /file:&quot;$(TargetPath)&quot; /console"
              Condition="Exists('$(ProgramFiles)\Microsoft FxCop 1.36\FxCopCmd.exe')" />
        <!-- When running on a 64 bit machine the $(ProgramFiles) variable will be set to c:\program files (x86) when running a 32 bit process which luckily for us Visual Studio and FxCop are.-->
      </Target>
    </Project>
  3. Open the Visual Studio
  4. File --> New Project (ctrl+shift+n)
  5. Select Other Project Types --> Visual Studio Solutions --> Blank Solution
  6. Name the solution FxCopIntegrated and press OK
  7. In Solution Explorer (ctrl +alt + L) right click the solution and select add new project.
  8. Select Visual C# --> Windows --> Class Library
  9. Name the library CodeBandit and press OK.
  10. In Solution Explorer right click the CodeBandit project and click unload project.
  11. If Visual Studio prompts to save files click "yes"
  12. In Solution Explorer right click the CodeBandit project and click "Edit CodeBandit.csproj"
  13. Navigate to the line after this (ctrl+g 52 on my machine):
    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  14.  Add this line to reference the file created in step 2:
    <Import Project="$(MSBuildExtensionsPath)\v3.5\FxCop.targets"/>
  15. In Solution Explorer right click the CodeBandit project and click reload project.
  16. If Visual Studio asks to close CodeBandit.csproj click "yes" and "yes" to save changes if prompted.
  17. Build the solution.  On my system I received these warnings:
    CA2210 : Microsoft.Design : Sign 'CodeBandit.dll' with a strong name key.
    CA1014 : Microsoft.Design : Mark 'CodeBandit.dll' with CLSCompliant(true) because it exposes externally visible types.
Option #2 Integrating FxCop across all solutions.
  1. Follow the steps from Option #1 to ensure everything is setup and working.
  2. Create a file: C:\Program Files (x86)\MSBuild\v3.5\Custom.After.Microsoft.Common.targets with the following text:
    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <Import Project="FxCop.Targets"/>
    </Project>
  3. Thats it, all the work was performed in Option #1 :)
  4. To verify this add a new VB project to the FxCopIntegrated solution.
  5. Building the newly added project I get these warnings:
    CA1020 : Microsoft.Design : Consider merging the types defined in 'ClassLibrary2' with another namespace.
    CA2210 : Microsoft.Design : Sign 'ClassLibrary2.dll' with a strong name key.
    CA1014 : Microsoft.Design : Mark 'ClassLibrary2.dll' with CLSCompliant(true) because it exposes externally visible types.
    CA1824 : Microsoft.Performance : Because assembly 'ClassLibrary2.dll' contains a ResX-based resource file, mark it with the NeutralResourcesLanguage attribute, specifying the language of the resources within the assembly. This could improve lookup performance the first time a resource is retrieved.
Thanks to John Robbins for pointing me to an old post by the Code Analysis team showing how to call FxCop in a post build event and having it run over the project without maintaining a separate FxCop project file.

4 comments:

Hire C# Programmer said...

The post is about Visual Studio Team System (VSTS) which has Code Analysis (FxCop) integrated into Visual Studio.It teaches how to be a better programmer, finds issues in codes, and makes APIs more user friendly.The post is good & informative hope to see more of such good post.

Anonymous said...

You are mistaken. I can prove it.

Hire C# Developer said...

The steps mentioned in the post for integrating FxCop into Visual Studio is understandable and can easily be used as it is explained with code and explained nicely.

Kiquenet said...

It's great, does works for VS2010 ?? it gives me good ideas for automation build using fxcop too

My issue: http://stackoverflow.com/questions/12935616/integrate-fxcop-in-vs-2010-modifying-csproj-file-using-addin

Integrate FxCop in VS 2010 modifying csproj file using an Addin

I have many projects in TFS, using VS2010. I have a Addin VS2010 that add some new business features for my company.

Now, it is required integrate FxCop and Visual Studio 2010 for older and new projects.

I(we) don't want to add FxCopCmd.exe to my Post-build events to run FxCop with every compilation.

I(we) don't want to modify Microsoft.CSharp.targets or Microsoft.Common.targets.

I want the programmer don't do anything, not modify properties project, not modify xml csproj file.

I want to be able to run FxCop when the programmer do Build on the project in Solution Explorer, and too when do Build programatically in Addin:

solution.DTE.ExecuteCommand("Build.RebuildSolution", "");
project.DTE.ExecuteCommand("Build.RebuildSelection", "");

I think the better option is using Solution Events in Addin VS2010 for modify csproj file

solutionEvents.ProjectAdded
solutionEvents.Opened

Any suggestions about all this ?