问题描述
我做了大量研究,没有找到合适的答案。这是场景。
我有一个针对.NET Framework 4编译的应用程序。在运行时,我希望该应用程序在.NET Framework 4.6中实际执行。 1。到目前为止,我发现了两个选择。
- 在.NET Framework 4.6.1下重新编译应用程序
- 使用version = v4.0 sku =。NETFramework,Version = v4.6.1将configure / startup / supportedRuntime元素添加到app.config中。
选项1是不可取的,因为它需要重新发布软件。
选项2并没有达到我的期望。似乎要检查是否安装了CLR 4.0(不是Framework 4.0),如果没有,则提示下载适当的SKU进行安装。安装后,该应用程序仍在.NET Framework 4.0下执行。
作为测试,并发布了此问题的原因,我创建了一个小型控制台应用程序,只需执行此操作
Console.WriteLine(System.Net.ServicePointManager.SecurityProtocol);
如果是根据.NET Framework 4编译的,则输出为
如果是根据.NET Framework 4.6编译的。 1,则输出为
嗯,您已经完成了app.config文件的输入。它启用了,用户必须先安装4.6.1才能使程序运行。他所要做的就是单击是按钮。并非经常执行此操作,因此当用户负责使用Windows Update保持其计算机更新时,应始终在计算机上存在4.6.1。如果他有意不接受,那么强迫就不太可能得到很好的解决。
但这实际上不是您要问的问题。您希望自己的程序表现,就像它安装在4.6.1上一样。那是非常一锅鱼。请注意2)无效,您不能轻易欺骗运行时。编译器嵌入了在您的可执行文件中,即是运行时用来确定其行为方式的文件。使用ildasm.exe进行查看,双击清单以查看它。您的app.config条目不会覆盖它。
最大的问题是.NET 4.5的根本区别在于大量打破了两者的变化运行时和框架程序集。足够重,可以保证将版本提高到5.0。但这总是会给客户带来很多痛苦和痛苦,如果微软运行针对4.0的程序,微软就会掏出书中的所有技巧,使4.5(及更高版本)的行为像4.0。
不只是一个把戏。一种核心方法是将参考程序集存储在c:\Program Files(x86)\Reference Assemblies目录中。他们存储定位包文件。最初生成程序时,使用的是存储在C:\程序文件(x86)\参考程序集\Microsoft\Framework.NETFramework\v4.0中的文件。如果您重新定位项目,则可以使用v4.6.1中存储的项目。他们有很大的不同。尤其是。
和其他技巧。根据[TargetFrameworkAttribute]选择性地打开在.NET 4.0发行版中进行的错误修复,对于错误的向后兼容性对于确保程序不会观察到更改的运行时行为很重要。而CLR充满了appcompat开关。我可以指向CoreCLR中的源代码文件,但看起来太吓人了:)
所以不,使编译为目标.NET 4.0的程序的行为类似于它无法在更高版本上运行。您了解到的注册表项和appcontext开关高度仅特定于ServicePointManager.SecurityProtocol属性。他们之所以在这里,是因为您不是唯一想要这样做的客户,TLS版本非常重要。只需确保新的枚举值不会触发您的程序即可。
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.
- Recompile the application under .NET Framework 4.6.1
- 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
If that is compiled against .NET Framework 4.6.1 then the output is
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.
这篇关于如何强制将针对.NET Framework 4编译的应用程序在.NET Framework 4.6.1下运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!