72

I have my project target 4.0. I updated it to 4.5 and VS added

<startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>

On top of changing TargetFrameworkVersion and I am curious if this is redundant. My understanding is that if runtime doesn't find supportedRuntime, it uses the .net version used to build exe. So in this case, the exe is built using 4.5 and it also has saying to use 4.5. Would it behave differently whether i have this or not and run it on a machine that only has 4.0?

Liath
  • 9,913
  • 9
  • 51
  • 81
user21479
  • 1,179
  • 2
  • 13
  • 21
  • Related: [How to: Configure an App to Support .NET Framework 4 or 4.5 @ MSDN](https://msdn.microsoft.com/en-us/library/jj152935.aspx) – Palec Jan 10 '17 at 11:47

2 Answers2

99

The MSDN documentation doesn't give any good explanations of this, but I found a blog post by Scott Hanselman titled ".NET Versioning and Multi-Targeting - .NET 4.5 is an in-place upgrade to .NET 4.0" that reveals:

If you are making a client app, like WinForms, Console, WPF, etc, this is all automatic. Your app.config contains that fact that you need .NET 4.5 and you'll even get a prompt to install it.

So the config entry is all about what happens if a user with .NET 4.0 on their machine (but not .NET 4.5) tries to run your .NET 4.5 app. Both .NET 4.0 and .NET 4.5 are built on version 4 of the CLR, so they're theoretically compatible; same binary formats and all that. The only difference between a binary built against .NET 4.0 and one built against .NET 4.5 is the libraries they reference.

So an app compiled for .NET 4.5 could run on a computer with only .NET 4.0 installed. However, it would get a runtime exception if you tried to use any APIs that didn't exist in 4.0.

If you have this config file entry, and a user with .NET 4.0 tries to run your app, the app will not run, and the user will be prompted to install .NET 4.5. (See screenshot in Scott's blog post.) This is a good default for most people.

If you don't have the config file entry, then a user with .NET 4.0 will be able to run your app, but will get a runtime exception if you try to call any methods or use any types that were added in 4.5. This will be a big pain for you as a developer and for your testers. You should only do this if you have specific requirements that your app must run on .NET 4.0 and must take advantage of new 4.5 features if they're present (and you'll have to be careful about exception handling and test extensively on both versions).

If you want to be able to run on .NET 4.0, but don't need any new 4.5 APIs, then your life is much simpler: just go to the Build tab of Project Properties, and target .NET 4.0. Then the compiler will ensure that you don't call any APIs that didn't exist in 4.0, and your app will run successfully on both .NET 4.0 and .NET 4.5 machines.

Joe White
  • 94,807
  • 60
  • 220
  • 330
  • Note: Say you want to target a new framework to make use of a behavior change (such as TLS 1.2 by default in 4.6), make sure you update the config to use the new sku or you will be wondering why re-targeting did nothing. – Joel McBeth Feb 06 '17 at 16:38
  • Is there any way to remove it, but reliably enforce a .NET 4.0 vs 4.5 version check in code? – Dai Mar 15 '17 at 05:29
  • @Dai nope, just "pseudo-reliable" way how to check .NET version in the code. Either [check registry](https://learn.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed) or some new feature (see [the mentioned blog](http://www.hanselman.com/blog/NETVersioningAndMultiTargetingNET45IsAnInplaceUpgradeToNET40.aspx)). It's not recommended, though. – xmedeko Jun 14 '17 at 08:46
  • @JoelMcBeth this is really good explanation !! I recently encountered similar kind of doubt in context of asp.net web application and posted SO [here](https://stackoverflow.com/questions/60897777/how-compilation-targetframework-4-x-x-and-httpruntime-targetframework) Can you please look at it ? I am scared if question is so confusing/unclear that no one responded so far. – rahulaga-msft Apr 03 '20 at 04:26
  • I wonder what would happen if a user has .NET 4.5 but the config file entry is set to use .NET 4.0. The .NET 4.5 APIs would be called without any problem? Can I assume that the behaviour is going to be the same as having the config file entry set to .NET 4.5? – Pedro Faustino Apr 09 '20 at 20:17
  • The config entry is quite confusing. After digging into MSDN, I got to know: version="runtime version or CLR version" but sku=".NET FW version". Why doesn't MSDN make this more clear? By the way, sku is a quite confusing name as well. – Cary Mar 29 '21 at 09:17
3

Answering @Dai comment and also addressing the fact that when running as a Windows service, you may not get a prompt to install the specified version in App.config file.

Is there any way to remove it, but reliably enforce a .NET 4.0 vs 4.5 version check in code?

Here is what I use to ensure that the current program is running on a given .NET Framework version, inspired from How do I detect at runtime that .NET version 4.5 is currently running your code?

/// <summary>
/// Throws an exception if the current version of the .NET Framework is smaller than the specified <see cref="supportedVersion"/>.
/// </summary>
/// <param name="supportedVersion">The minimum supported version of the .NET Framework on which the current program can run.
/// The version to use is not the marketing version, but the file version of mscorlib.dll.
/// See <see href="https://blogs.msdn.microsoft.com/dougste/2016/03/17/file-version-history-for-clr-4-x/">File version history for CLR 4.x</see> and/or <see href="https://it.wikipedia.org/wiki/.NET_Framework#Versioni">.NET Framework Versioni (Build pubblicata)</see> for the version to use.
/// </param>
/// <exception cref="NotSupportedException">The current version of the .NET Framework is smaller than the specified <see cref="supportedVersion"/>.</exception>
/// <returns>The version of the .NET Framework on which the current program is running.</returns>
public static Version EnsureSupportedDotNetFrameworkVersion(Version supportedVersion)
{
    var fileVersion = typeof(int).Assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
    var currentVersion = new Version(fileVersion.Version);
    if (currentVersion < supportedVersion)
        throw new NotSupportedException($"Microsoft .NET Framework {supportedVersion} or newer is required. Current version ({currentVersion}) is not supported.");
    return currentVersion;
}

Example usage to ensure running on .NET 4.6.2:

var v462 = new Version(4, 6, 1590, 0);
EnsureSupportedDotNetFrameworkVersion(v462);
0xced
  • 25,219
  • 10
  • 103
  • 255