Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
250 views
in Technique[技术] by (71.8m points)

clr - How do I force an application compiled to target .NET Framework 4 to run under .NET framework 4.6.1?

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.

  1. Recompile the application under .NET Framework 4.6.1
  2. Add the configuration/startup/supportedRuntime element to app.config with version="v4.0" sku=".NETFramework,Version=v4.6.1"

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 AssembliesMicrosoftFramework.NETFrameworkv4.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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...