?

Log in

No account? Create an account
Gavin Greig [userpic]

FxCop: breaking the build, with useful warnings

June 14th, 2009 (08:24 pm)
current location: KY16 8SX

Visual Studio Team System includes Code Analysis, an integrated tool that will analyse your .NET assembly once you’ve built it, and identify a range of common problems (specifically, ways in which your code doesn't meet the Framework Design Guidelines). These can raise warnings or even errors as part of the build process.

If you have a less capable (cheaper) edition of Visual Studio, then all you have is Code Analysis’ little brother, FxCop. FxCop is not integrated into Visual Studio, and has to be run as a separate tool.

It would be nice to be able to use FxCop to generate warnings as part of the build, and even make the build break if any warnings occur. After a bit of a look around this weekend, I found that although bits of the solution were out there, some of them were a bit complex and there wasn’t one simple recommendation that would do just that.

So here it is:

   1: <PropertyGroup>
   2:   <FxCopResults>$(ProjectDir)obj\$(Configuration)\FxCopResults.xml</FxCopResults>
   3:   <PostBuildEvent>"%25ProgramFiles%25\Microsoft FxCop 1.36\FxCopCmd.exe" /file:"$(TargetPath)" /console /out:"$(ProjectDir)obj\$(ConfigurationName)\FxCopResults.xml"</PostBuildEvent>
   4: </PropertyGroup>
   5: <Target Name="BeforeBuild">
   6:   <Delete Files="$(FxCopResults)" ContinueOnError="true" />
   7: </Target>
   8: <Target Name="AfterBuild">
   9:   <Error Text="One or more FxCop warnings occurred." Condition="Exists('$(FxCopResults)')" />
  10: </Target>

Insert this snippet into your project file (modifying as appropriate in line 3 if you’re using a different version of FxCop); FxCop warnings will appear – as warnings, not as errors – in the Output window and the Error List, and the build will fail if any occur. If the warnings are associated with a property, event or method then you’ll be able to double-click on the warning to jump to the location in code.

Here's how it works. As indicated on the Visual Studio Code Analysis Team Blog, when the command line version of FxCop (FxCopCmd.exe)  is run as a PostBuildEvent, with output directed to the console, the resulting warnings appear in the Output window.

Running FxCop from MSBuild in some other way (such as using an Exec task, or by using the FxCop task in the MSBuild Community Tasks project) can generate an output file or a single monolithic capture of the console output; but the output won’t appear as individual warnings in the Output or Error List windows. That’s why it must be run as a PostBuildEvent.

That will result in individual, actionable warnings in the build output, but it won’t break the build. So how do we do that?

Well, luckily, a PostBuildEvent is not the end of the build process. The standard MSBuild target AfterBuild will run after a PostBuildEvent; so if as well as the console output from FxCopCmd we also request an output file, we can then check for its existence in the AfterBuild and generate an error if it’s found. No output file is generated if no warnings occur, and we can delete it in the BeforeBuild target to ensure that it isn’t left over from a previous build.

You may notice that the location of the output file is specified twice, in slightly different ways; once in the FxCopResults property in line 2, and again towards the end of the PostBuildEvent in line 3. Although it looks as though it woudl be possible to rationalise these into one property, it turns out that's not possible. The PostBuildEvent doesn't quite evaluate things in the same way as MSBuild, so it is necessary to specify the location again.

What this solution does:
  • Shows individual, actionable FxCop warnings in the Output window and Error List.
  • Jump to code location if warning is associated with a property, event or method.
  • Breaks the build if one or more FxCop warnings occur.
What this solution doesn’t do, but Code Analysis does:
  • It doesn't support automatic in-code suppression of warnings directly from the context menu in the Error List. You'll need to run FxCop separately to generate these suppression messages, or write them by hand; but at least you'll know when to bother and when it isn't necessary.
  • Doesn’t (directly) provide finer control of which FxCop rules to run against a particular project. You would need to create an FxCop project file and modify the PostBuildEvent command line to achieve this.
  • Doesn't allow some rules to generate warnings while others generate errors.

If you want more complex configuration then it may be worth checking out John Rayner’s post on the subject, but for me, that’s a step too far. I don’t want to be able to configure FxCop too much; I want it to pass or fail, so long as I have in-code suppression for warnings that turn out to be unwarranted. (Remember to define the CODE_ANALYSIS conditional compilation symbol in order for the SuppressMessage attribute to work!)

This post was also an opportunity to try out the Code Snippet plug-in for Live Writer. I would have liked to use the excellent SyntaxHighlighter, which appears to be the Acme of such things, but its use of JavaScript means it’s not appropriate for LiveJournal. :-( CodeSnippet looks reasonable, but doesn’t support line-wrapping, or plain text copying of the source, as SyntaxHighlighter would have done.

Edit: it also seems to generate some white space that LJ isn't happy with, subsequently removed by hand.