This shows up when you press F1 in the Framework and References dialog:
By default for new projects, the targeted framework is set to .NET Framework 4. The IDE does not support modifying the targeted framework, but you can change it manually.
In the project file (.vcxproj), the default targeted framework is represented by the v4.0 property element. To change the targeted framework, unload the project, use a text editor to open the project file, and then change the value of the property element from v4.0 to another version that is installed on your server. For example, if you specify v3.5, which represents the .NET Framework v3.5, Visual Studio 2008 SP1 must be installed. Save and close the file, reload the project, and verify that the targeted framework is displayed in the property page.*
That's not terribly accurate on converted projects, you'll have to add the <TargetFrameworkVersion>
element yourself. Put it in the PropertyGroup labeled "Globals":
<PropertyGroup Label="Globals">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<others...>
</PropertyGroup>
The story is different when you use VS2012 and up, the first version of VS that acquired the Platform Toolset setting in the General property page. You must then select "v90" to get a proper build that targets 3.5. It is however clumsy, you must have all intermediate versions of VS installed on the machine to have that selection available.
Why you need VS2008 installed requires an explanation by itself. The core issue is that the C runtime library (msvcrt100.dll and up) contains .NET code to support managed code execution. The crucial detail is a module initializer that ensures the CRT is correctly initialized in program that uses C++/CLI code. That code always targets .NET 4 and since it is hard-baked into msvcrt100.dll (and up) you always have a rock-hard dependency on the v4.0.30319 runtime. You can only ever have a pure v2.0.50727 dependency when you use the old C runtime, msvcrt90.dll. You can only be sure that you have a msvcrt90.dll dependency when you use the compiler's #include files of VS2008.
Cold hard fact that it is pretty necessary to move to .NET 4 soon, you'll struggle with build problems like this if you don't. There are very few practical obstacles to that, .NET 4 is widely available for free on all targets you'd imagine. Overcoming the FUD that is associated with moving to a higher runtime version is generally only the real issue. No reasons for fear and doubt, it is stable.
One of the Roslyn engineers who specializes in understanding optimization of stack usage took a look at this and reports to me that there seems to be a problem in the interaction between the way the C# compiler generates local variable stores and the way the JIT compiler does register scheduling in the corresponding x86 code. The result is suboptimal code generation on the loads and stores of the locals.
For some reason unclear to all of us, the problematic code generation path is avoided when the JITter knows that the block is in a try-protected region.
This is pretty weird. We'll follow up with the JITter team and see whether we can get a bug entered so that they can fix this.
Also, we are working on improvements for Roslyn to the C# and VB compilers' algorithms for determining when locals can be made "ephemeral" -- that is, just pushed and popped on the stack, rather than allocated a specific location on the stack for the duration of the activation. We believe that the JITter will be able to do a better job of register allocation and whatnot if we give it better hints about when locals can be made "dead" earlier.
Thanks for bringing this to our attention, and apologies for the odd behaviour.
Best Answer
Right click on the setup project in the solution explorer -> View -> Launch Conditions and set the appropriate .NET framework version: