August 2008 - Posts

Back in October of last year, Krzysztof Cwalina talked about the multi-targeting changes in Visual Studio 2008 and .NET 3.5. He mentioned the limitations in its design that could cause an application that explicitly targets .NET Framework 2.0 and .NET Framework 3.0 to accidently take a dependency on a new member or type that did not exist in the RTM version of that framework. As a workaround, he posted the source code of a Code Analysis/FxCop rule that could detect and fire on a member that took one of these dependencies.

A little while before he wrote that post, my team at the time, the Code Analysis team, was approached to see if we could ship a similar rule out of the box. Unfortunately, we ran out of time to get it included in Visual Studio 2008 RTM and FxCop Beta 2, however, I’m pleased to announce that we’ve added the rule, Use only API from targeted framework, to Visual Studio 2008 SP1 and FxCop 1.36 RTM release.

Note: The Visual Studio integration for this rule is only available in editions that support Code Analysis; Visual Studio Team Development Edition and Visual Studio Team Suite.

 

How this rule works

In Visual Studio, this rule reads the current targeted framework stored in the C# or Visual Basic project and fires on any usage of API that was not included in the RTM version of that framework. Whereas, in FxCop, the rule reads the targeted framework stored within the FxCop project or passed via the command-line.

The following table attempts to explain this:

 

When Target Framework (in Project properties or in FxCop project options/command-line) is set to:

Code Analysis/FxCop fires on usage of:

.NET Framework 2.0

.NET Framework 3.0

.NET Framework  3.5

.NET Framework 2.0

 

 

 

.NET Framework 2.0 SP1

 

.NET Framework 2.0 SP2

 

.NET Framework 3.0

 

 

.NET Framework 3.0 SP1

 

.NET Framework 3.0 SP2

 

.NET Framework 3.5

 

.NET Framework 3.5 SP1

MSBuild prevents a user from mixing these combinations in Visual Studio, so only FxCop can fire on this.
Client-only Framework subset is not supported.

For example, when a user selects .NET Framework 3.0 as their project’s target framework, Code Analysis and FxCop will fire on any usage of members and types that were introduced in .NET Framework 2.0 SP1 and SP2, .NET Framework 3.0 SP1 and SP2, .NET Framework 3.5 and .NET Framework 3.5 SP1. This is because on a fresh install of .NET Framework 3.0 (such as on Vista RTM), none of these service packs or frameworks are installed.  

Enabling in Visual Studio

By default, Visual Studio projects with the default Code Analysis settings will already have the rule enabled. To check this, do the following:

  1. In Solution Explorer, right-click on your project and choose Properties
  2. Choose the Code Analysis tab
  3. Expand the Portability node and ensure that Use only API from targeted framework is checked

Use only API from targeted framework

Once this rule has been enabled, you need to make sure that you targeting the framework that you plan to release your application on. To verify this, do the following: 

For C# projects:
  1. In Solution Explorer, right-click on your project and choose Properties
  2. Choose the Application tab
  3. From the Targeted Framework drop down, choose the framework that your application is targeting

Target Framework in C# project properties 

For Visual Basic projects:
  1. In Solution Explorer, right-click on your project and choose Properties
  2. Choose the Build tab and click Advanced Compile Options…
  3. From the Target framework (all configurations) drop down, choose the framework that your application is targeting

Target Framework in Visual Basic project properties

Once you’ve done the above, running Code Analysis (Analyze -> Run Code Analysis) should now fire on any service pack dependencies your project has taken on. For example, using DateTimeOffset in a project that is set to target .NET Framework 2.0, will cause the following warning to output.

'Use only API from targeted Framework' warning 

Enabling in FxCop

In contrast to Visual Studio, Use only API from targeted framework does not fire by default in FxCop. This is because FxCop does not have access to the project (.csproj, .vbproj) of the assembly that it is analyzing, and hence cannot automatically determine the Framework your application is targeting. Because of this, you need explicitly specify it; either via the FxCop project or via the command-line.

Enabling using an FxCop project

By default, FxCop projects will already have the rule enabled. To check this, do the following:

  1. Open your FxCop project in FxCop
  2. Choose the Rules tab
  3. Expand the Portability node and ensure that Use only API from targeted framework is checked

Use only API from target framewor

Once this rule has been enabled, it will not fire until you tell FxCop the framework you are targeting. To do this, do the following:

  1. Open your FxCop project in FxCop
  2. Choose Project -> Options and then choose the Spelling & Analysis tab
  3. From the Target Framework drop down, choose the framework you are targeting. Typically this would match the value specified in your C#, Visual Basic or C++ project’s properties.
  4. Click OK

Target Framework in FxCop

Note: You can make this the default for all new FxCop projects and for the command-line by clicking Defaults… after you open the Project Options dialog and then following the rest of the steps above.

Once you’ve done the above, running analysis (Project -> Analyze) should now fire on any service pack dependencies your application has taken on. For example, using DateTimeOffset in a assembly that is set to target .NET Framework 2.0, will cause the following error to output:

'Use only API from targeted framework' error  

Enabling via the command-line

While the preferred method to specify the target framework is by using an FxCop project as described above, you can also specify it explicitly via the command-line. The new /targetframeworkversion switch was added for this purpose. Its valid values are described below:

Argument

Description

/targetframeworkversion:2.0

Specifies .NET Framework 2.0

/targetframeworkversion:3.0

Specifies .NET Framework 3.0

/targetframeworkversion:3.5

Specifies .NET Framework 3.5

/targetframeworkversion:none

Disables the rule.

This is the default. However, it can useful to specify this argument if you want to override the associated setting stored in an FxCop project that is passed on the same command-line.

Specifying any of these arguments on a command-line will override the target framework setting stored in the FxCop project.

An example command-line would be the following:

FxCopCmd.exe /file:MyAssembly.dll /console /targetframeworkversion:2.0

Disabling the rule or targeting specific service packs

Use only API from targeted framework does not have support for targeting specific service packs, such as .NET Framework 2.0 SP1. If you want to deliberately take a dependency on a service pack, simply disable the rule by unchecking instead of checking the rule in the Enabling in Visual Studio and Enabling in FxCop sections.

Posted by David Kean | 21 comment(s)
Filed under:

One of the small, but rather useful changes we made in 1.36 was to gray out privates and internals in the Targets tree. This makes it quick and easy to see the public API for a particular assembly.

image 

This is similar to the feature already available in .NET Reflector, except that FxCop also grays out any member that is not visible outside of the assembly; for example, a public method within an internal class.

Posted by David Kean | with no comments
Filed under:

After what has to be the longest beta period for a product (after Gmail) - we've finally released the final version of FxCop 1.36.

I've talked in the past about some the improvements in this release, including:

  • 200+ bug fixes that reduce noise, missing analysis and rule crashes
  • Support for analyzing anonymous methods and lambda expressions
  • New option for skipping analysis over tool generated code
  • Spell checker libraries now ship in the box
  • Changes in the way references are resolved and located
  • Better support for C++/CLI and the Compact Framework
  • Language 'friendly' API names in the UI and resolutions (ie Visual Basic syntax if running over a Visual Basic binary)
  • New globalization, design and usage rules
  • New rule for targeting specific versions of the Framework
  • Performance improvements that cut analysis by 2x and use half as much memory
  • Documentation that is now available on MSDN

    This is a great release - download it, and feel free to head over to the Code Analysis forum to tell my old team what you think.

  • Posted by David Kean | 9 comment(s)
    Filed under: ,