Saturday, March 15, 2014

Visual C# projects properties manual customization - 1/3

Programming language : C#
Topic category : IDE
OS : Windows
IDE : Visual C# 2010 Express

Context

I started a C# library (DLL) development for the company I'm currently working for, using their legacy .NET Framework version and tools : the outdated .NET v2.0 on Visual C# 2005. I was requested to migrate the solution to the more recent .NET v4.0 on Visual C# 2010 Express. This was very easy using the IDE integrated project migration tool, but I wanted to keep the .NET v2.0 version of the solution, and have it coexisting with the new .NET v4.0 version. Things turned out to be more complex than initialy expected...

Framework version project property

Coming from the C++ world and being quite experienced with the Visual C++ environment, I would have expected Visual C# would also offer a lot of project properties and be very flexible. I forked the default Debug and Release solution configurations into Debug_2_0 and Release_2_0 for the legacy .NET v2.0 version of the libraries. I set the current solution configuration to Debug_2_0, opened the projects properties > Application and set the Target Framework to .NET Framework 2.0.


Once the solution was rebuilt, I ensured the result actually referred to .NET v2.0. I used the dedicated Visual Studio companion tool MSIL Disassembler [1] (ildasm.exe). I could confirm my library target framework was .NET v2.0 for the Debug_2_0 configuration.


But when checking whether the Target Framework was .NET Framework 4.0 in the Debug solution configuration, I found out the property was set to .NET Framework 2.0 as well. I understood the Target Framework property was not project, but solution configuration dependent.

In the intricacies of the project description file

Although it did not answer my question, I was given a decisive clue by a StackOverflow topic [2]: I found out it was possible to bypass limitations of the GUI about project properties by editing the project description file (.CSPROJ extension). Such files are just XML files and thus can be edited manually.
  • I searched for a possible candidate for the Target Framework property. I found it : TargetFrameworkVersion.

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> ... <PropertyGroup> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> ... </PropertyGroup> ... </Project>
  • I copied the property into the Debug_2_0 and Release_2_0 conditional property groups.

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> ... <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_2_0|AnyCPU'"> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> ... </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug_2_0|AnyCPU'"> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> ... </PropertyGroup> ... </Project>
  • I set the copied tags value to v2.0.

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> ... <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_2_0|AnyCPU'"> <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> ... </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug_2_0|AnyCPU'"> <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> ... </PropertyGroup> ... </Project>
  • Finally, I validated my manual modifications using the MSIL Disassembler.



Conclusion

Despite I was a little disappointed to meet limitations in the Visual C# GUI for such basic needs as per project .NET framework version customization, learning how to bypass them was very beneficial. Then, I did not know I was about to make a much more advanced use of it.

References

[1] Microsoft Developer Network (MSDN): Ildasm.exe (IL Disassembler)
[2] Stackoverflow: question 8161183 - visual studio 2010 compiler conditions based on target framework