I have done considerable research and not found any suitable answer. Here is the scenario.
I have an application which was compiled to target .NET Framework 4. At runtime I want that application to actually execute within the .NET Framework 4.6.1. I found two options so far.
Option 1 is not desirable as it would require a re-release of software.
Option 2 doesn't do what I would expect. It seems to check if CLR 4.0 (not framework 4.0) is installed and if not prompts to download the appropriate SKU to install it. After being installed, the application still executes under .NET Framework 4.0
As a test, and the reason this question is posted, I created a small console app which simply does this
Console.WriteLine(System.Net.ServicePointManager.SecurityProtocol);
If that is compiled against .NET Framework 4 then the output is
Ssl3, Tls
If that is compiled against .NET Framework 4.6.1 then the output is
Tls, Tls11, Tls12
The specific ServicePointManager.SecurityProtocol determination is quite unrelated to the general question of 4 vs 4.6.1 framework for which I'm afraid there's not definitive answer, because it's not relevant in the general case (all cases are probably specific, if you will).
For the specific answer, this is described here: Mitigation: TLS Protocols
Starting with the .NET Framework 4.6, the System.Net.ServicePointManager and System.Net.Security.SslStream classes are allowed to use one of the following three protocols: Tls1.0, Tls1.1, or Tls 1.2. The SSL3.0 protocol and RC4 cipher are not supported.
If the 4.6+ is installed, then you can indeed change the behavior of your program w/o recompiling it, as detailed in the article, just add this line to your .config files:
<configuration>
...
<runtime>
...
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false" />
</runtime>
...
</configuration>
I am ... asking about the general case of forcing an application compiled against framework 4.0 to run using framework 4.6.1
Well, you already did with app.config file entry. It empowers this feature, the user can't get the program running without installing 4.6.1 first. All he has to do is click the Yes button. Not that this gets exercised very often, 4.6.1 should always be present on the machine when the user is responsible about keeping his machine updated with Windows Update. If he intentionally doesn't then "forcing" isn't very likely to be received well.
But that is not actually what your question is about. You want your program to behave like it is installed on 4.6.1. That's a very different kettle of fish. Do note that 2) did not work, you can't fool the runtime that easily. The compiler embedded a TargetFrameworkAttribute attribute in your executable file, that's the one the runtime uses to determine how it should behave. Have a look-see with ildasm.exe, double-click the manifest to see it. Your app.config entry does not override it.
Biggest issue is that .NET 4.5 is rather fundamentally different with heavily breaking changes in the both the runtime and the framework assemblies. Heavy enough to would have warranted bumping the version up to 5.0. But that always causes lots of pain and suffering on the customers, Microsoft pulled out every trick in the book to make 4.5 (and up) behave like 4.0 if it runs a program that targeted 4.0.
Not just one trick. One core approach were the reference assemblies stored in c:\Program Files (x86)\Reference Assemblies directory. They store the targeting pack files. You used the ones stored in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0 when you originally built your program. If you retarget your project then you'd use the ones stored in v4.6.1. They are very different. And notably the SecurityProtocolType enum you are talking about is different, it acquired two new values. This is a breaking change, a .NET 4.0 program is liable to suffer a heart-attack when it sees SecurityProtocolType.Tls12, it has no idea whatsoever what it could mean. Building a program with the wrong targeting pack files can cause deeply mystifying exceptions.
And other tricks. Bug fixes made in post .NET 4.0 releases are selectively turned on depending on the [TargetFrameworkAttribute], backwards compatibility for bugs is important to ensure that a program doesn't observe changed runtime behavior. And the CLR is filled to the brim with appcompat switches. I could point to the source code file in CoreCLR but it is entirely too scary to look at :)
So no, making a program compiled to target .NET 4.0 behave like it runs on a higher version is not possible. The registry key and the appcontext switch you learned about is highly specific to just the ServicePointManager.SecurityProtocol property. They are there simply because you are not the only customer that wants to do this, TLS versions are rather important. Just make sure that the new enum values don't trip up your program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With