A lot has been said on the Internet about .NET Framework 4.5 being an "in-place" update for .NET Framework 4.0. I'm not sure where it all started from, but it has definitely made huge impact on the community. So if you have .NET 4.0 installed and then you install .NET 4.5, you are not able to use the old framework anymore? That's what a lot of people believe. Which creates a lot of confusion and postings like this: http://stackoverflow.com/questions/11458159/how-to-keep-net-4-0-behavior-if-net-4-5-is-installed
We have a Windows Form application that targets .Net Framework 4.0. After installing .Net Framework 4.5, the application starts crashing. We'll have to investigate the crashes and we'll most probably have to fix things on our side. But is there a setting we can turn on to keep the old behavior until we are ready to use .Net 4.5?
Of course. You install a new version of the framework and it breaks all of your applications. Poor guy... Or course I wouldn't mention this posting here if it didn't have this in the end of the discussion:
I discussed this over email with original question poster - "Sly". Thanks Sly for helping investigate. It turns out that .NET4 and .NET4.5 behave the same way for Dispose(waithandle) API. So this problem is potentially unrelated to .NET4.5.
Oh that's really good news. At least I don't have to uninstall .NET 4.5 from my machine.
A lot of people, not only on the Internet, think that installing .NET 4.5 on your local machine or even on your servers will automatically make your applications take advantage of the new features, probably improve performance or just break your applications. Depending on lucky you are.
I didn't take it seriously in the beginning but at some point I have decided to really think about it. Can Microsoft create such a trap for its users? How can that possibly be true? So I have done a little investigation myself.
In our investigation we will try to answer these questions:
Unfortunately there is no universal proper way to determine the .NET version. The best we can do is to load some of the standard .NET assemblies and check its version. But this method is also not ideal because some assemblies may be present in one version of the framework but not in another one. And there are other catches besides that.
Let's try simpler approach and find the framework version by executing some code that behaves differently in .NET 4.0 and 4.5. This MSDN page contains a list of .NET 4.5 breaking changes: http://msdn.microsoft.com/en-us/library/hh367887.aspx
Let's pick some breaking change that is easy to verify, for example:
In applications that target the .NET Framework 4.5, trailing dots at the end of a path segment in an original URI string (for example, http://www.proseware.com/LLC./About.aspx) are preserved. (Note that path segments that consist exactly of one or two dots, such as http://www.proseware.com/.. orhttp://www.proseware.com/./default.htm, are removed, but path segments that have more than two consecutive dots (such as http://localhost/dir1/.../dir2) are preserved.
Which means we can write a simple program to check if we are running on .NET 4.5:
Here we create a string URI with three consecutive dots. If after creating a Uri object and converting it back to string we get the same three dots, it means we are on .NET 4.5. Otherwise, if dots are not preserved we are using a different framework version.
Let's compile this program in Visual Studio 2012 with all the default project settings and run it. On my machine it gives the following output (first line is just a CLR version):
4.0.30319.18046
http://localhost/dir1/.../dir2
4.5
The result is expected. All three dots are preserved. Now let's look at our assembly in ildasm and see if we can find any clues as to which version of the framework to use. For that let's just type in VS2012 command line (while in the debug directory):
ConsoleApplication3\bin\Debug>ildasm ConsoleApplication3.exe
In the opened window let's click on the manifest tree view item to find the following text among other information:
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 01 00 54 // ,Version=v4.5..T
0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl
61 79 4E 61 6D 65 12 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram
65 77 6F 72 6B 20 34 2E 35 ) // ework 4.5
Interesting. Some TargetFrameworkAttribute. Now let's try and change the Target Framework in our project properties to .NET 4.0. Rebuild it, run ildasm again and we will get...
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 30 01 00 54 // ,Version=v4.0..T
0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl
61 79 4E 61 6D 65 10 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram
65 77 6F 72 6B 20 34 ) // ework 4
Same thing but the version has been changed to 4.0 which is expected.
Now that out project is build with .NET 4.0 let's run it again:
4.0.30319.18046
http://localhost/dir1/dir2
something else
It's a different output! Which means the MSDN was right saying that this is a breaking change. (Note, however, that we have the same version of the CLR which just illustrates that CLR version and .NET version are totally different things)
So far so good. At least we are able to use the old framework with the new framework installed.
As we can see, selecting a different framework version in Visual Studio changes the TargetFrameworkAttribute value in the assembly manifest. Which probably means Visual Studio adds this attribute automatically. To verify our assumption let's try a little experiment. Add the TargetFrameworkAttribute attribute in the program code by hand:
Now if we try to build it...
Error 4 Duplicate 'System.Runtime.Versioning.TargetFramework' attribute
Boom. Compilation error. Which actually makes sense. If Visual Studio adds the same attribute itself, that would be weird if we could add it as well. For example if in the project properties we have Target Framework Version set to 4.0 but in our code we add the TargetFrameworkAttribute for 4.5, who should win in this situation? No one. Visual Studio will just give us a nice error saying it's a duplicate attribute.
Okay. So Visual Studio always adds the TargetFrameworkAttribute based on the project settings. But do we have to build our project in Visual Studio? Of course not! We can just use C# compiler "csc.exe". So let's go to the folder containing our program code (Program.cs) and compile it from the command line:
ConsoleApplication3>csc Program.cs
It compiles successfully. And if we open the resulting assembly "Program.exe" in ildasm we will see the same TargetFrameworkAttribute that we set in our code. Which is exactly what we expected. Needless to say, if we run this program it will output the correct .NET framework version which is 4.5.
Great. We can add the TargetFrameworkAttribute in our code if compiling with csc.exe but then we may have another question. What if we don't add this attribute and still compile with csc.exe? What will be in the manifest in this case? We don't set it ourselves in the code and we also don't have Visual Studio to set it for us. Any guesses? Let's try that.
... And there is nothing in the metadata saying which framework version to use! Crazy. So the only thing we can do is try and run our program and see the output:
4.0.30319.18046
http://localhost/dir1/dir2
something else
Wow! The same output as for the .NET 4.0-targeted program. What does that mean for us? In the absence of the TargetFrameworkAttribute it doesn't even use the latest version of the framework installed. What a surprise. Actually I don't have an answer to this question. How it selects framework version in this case is still to be figured out. Maybe there is some registry setting for that.
I have tried running the program on three different machines (Windows 7, Windows 8, Windows Server 2012) and they all gave me the same results (only CLR version was a bit different in last several digits).
So to summarize and answer the question we asked:
We have a Windows Form application that targets .Net Framework 4.0. After installing .Net Framework 4.5, the application starts crashing. We'll have to investigate the crashes and we'll most probably have to fix things on our side. But is there a setting we can turn on to keep the old behavior until we are ready to use .Net 4.5?
Of course. You install a new version of the framework and it breaks all of your applications. Poor guy... Or course I wouldn't mention this posting here if it didn't have this in the end of the discussion:
I discussed this over email with original question poster - "Sly". Thanks Sly for helping investigate. It turns out that .NET4 and .NET4.5 behave the same way for Dispose(waithandle) API. So this problem is potentially unrelated to .NET4.5.
Oh that's really good news. At least I don't have to uninstall .NET 4.5 from my machine.
A lot of people, not only on the Internet, think that installing .NET 4.5 on your local machine or even on your servers will automatically make your applications take advantage of the new features, probably improve performance or just break your applications. Depending on lucky you are.
I didn't take it seriously in the beginning but at some point I have decided to really think about it. Can Microsoft create such a trap for its users? How can that possibly be true? So I have done a little investigation myself.
In our investigation we will try to answer these questions:
- Can we still use .NET 4.0 after "in-place" update of .NET 4.5 was installed?
- Will our application automatically start using .NET 4.5?
- How does the system decide which version of .NET it should execute our application with?
Unfortunately there is no universal proper way to determine the .NET version. The best we can do is to load some of the standard .NET assemblies and check its version. But this method is also not ideal because some assemblies may be present in one version of the framework but not in another one. And there are other catches besides that.
Let's try simpler approach and find the framework version by executing some code that behaves differently in .NET 4.0 and 4.5. This MSDN page contains a list of .NET 4.5 breaking changes: http://msdn.microsoft.com/en-us/library/hh367887.aspx
Let's pick some breaking change that is easy to verify, for example:
In applications that target the .NET Framework 4.5, trailing dots at the end of a path segment in an original URI string (for example, http://www.proseware.com/LLC./About.aspx) are preserved. (Note that path segments that consist exactly of one or two dots, such as http://www.proseware.com/.. orhttp://www.proseware.com/./default.htm, are removed, but path segments that have more than two consecutive dots (such as http://localhost/dir1/.../dir2) are preserved.
Which means we can write a simple program to check if we are running on .NET 4.5:
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Environment.Version);
const string originalUrl = "http://localhost/dir1/.../dir2";
Uri uri = new Uri(originalUrl);
string convertedUri = uri.ToString();
Console.WriteLine(convertedUri);
Console.WriteLine(convertedUri == originalUrl ? "4.5" : "something else");
}
}
}
Here we create a string URI with three consecutive dots. If after creating a Uri object and converting it back to string we get the same three dots, it means we are on .NET 4.5. Otherwise, if dots are not preserved we are using a different framework version.
Let's compile this program in Visual Studio 2012 with all the default project settings and run it. On my machine it gives the following output (first line is just a CLR version):
4.0.30319.18046
http://localhost/dir1/.../dir2
4.5
The result is expected. All three dots are preserved. Now let's look at our assembly in ildasm and see if we can find any clues as to which version of the framework to use. For that let's just type in VS2012 command line (while in the debug directory):
ConsoleApplication3\bin\Debug>ildasm ConsoleApplication3.exe
In the opened window let's click on the manifest tree view item to find the following text among other information:
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 01 00 54 // ,Version=v4.5..T
0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl
61 79 4E 61 6D 65 12 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram
65 77 6F 72 6B 20 34 2E 35 ) // ework 4.5
Interesting. Some TargetFrameworkAttribute. Now let's try and change the Target Framework in our project properties to .NET 4.0. Rebuild it, run ildasm again and we will get...
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 30 01 00 54 // ,Version=v4.0..T
0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl
61 79 4E 61 6D 65 10 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram
65 77 6F 72 6B 20 34 ) // ework 4
Same thing but the version has been changed to 4.0 which is expected.
Now that out project is build with .NET 4.0 let's run it again:
4.0.30319.18046
http://localhost/dir1/dir2
something else
It's a different output! Which means the MSDN was right saying that this is a breaking change. (Note, however, that we have the same version of the CLR which just illustrates that CLR version and .NET version are totally different things)
So far so good. At least we are able to use the old framework with the new framework installed.
As we can see, selecting a different framework version in Visual Studio changes the TargetFrameworkAttribute value in the assembly manifest. Which probably means Visual Studio adds this attribute automatically. To verify our assumption let's try a little experiment. Add the TargetFrameworkAttribute attribute in the program code by hand:
using System;
[assembly: System.Runtime.Versioning.TargetFramework(".NETFramework,Version=v4.5")]
namespace ConsoleApplication3
{
class Program
Now if we try to build it...
Error 4 Duplicate 'System.Runtime.Versioning.TargetFramework' attribute
Boom. Compilation error. Which actually makes sense. If Visual Studio adds the same attribute itself, that would be weird if we could add it as well. For example if in the project properties we have Target Framework Version set to 4.0 but in our code we add the TargetFrameworkAttribute for 4.5, who should win in this situation? No one. Visual Studio will just give us a nice error saying it's a duplicate attribute.
Okay. So Visual Studio always adds the TargetFrameworkAttribute based on the project settings. But do we have to build our project in Visual Studio? Of course not! We can just use C# compiler "csc.exe". So let's go to the folder containing our program code (Program.cs) and compile it from the command line:
ConsoleApplication3>csc Program.cs
It compiles successfully. And if we open the resulting assembly "Program.exe" in ildasm we will see the same TargetFrameworkAttribute that we set in our code. Which is exactly what we expected. Needless to say, if we run this program it will output the correct .NET framework version which is 4.5.
Great. We can add the TargetFrameworkAttribute in our code if compiling with csc.exe but then we may have another question. What if we don't add this attribute and still compile with csc.exe? What will be in the manifest in this case? We don't set it ourselves in the code and we also don't have Visual Studio to set it for us. Any guesses? Let's try that.
... And there is nothing in the metadata saying which framework version to use! Crazy. So the only thing we can do is try and run our program and see the output:
4.0.30319.18046
http://localhost/dir1/dir2
something else
Wow! The same output as for the .NET 4.0-targeted program. What does that mean for us? In the absence of the TargetFrameworkAttribute it doesn't even use the latest version of the framework installed. What a surprise. Actually I don't have an answer to this question. How it selects framework version in this case is still to be figured out. Maybe there is some registry setting for that.
I have tried running the program on three different machines (Windows 7, Windows 8, Windows Server 2012) and they all gave me the same results (only CLR version was a bit different in last several digits).
So to summarize and answer the question we asked:
- Yes, we still can use the .NET 4.0 even after 4.5 is installed.
- No, existing applications don't magically start using .NET 4.5. If they are built with Visual Studio or similar tools (e.g. msbuild), the manifest will contain the TargetFrameworkAttribute with the framework version specified in the project properties. Even if we don't use Visual Studio tools we can specify that attribute directly in code. In either case the value specified in the attribute will be used at run time as a framework version.
- If there is no TargetFrameworkAttribute specified, version 4.0 is used (or maybe even some other version but definitely not 4.5). How this is determined is unknown. But this question requires its own investigation.
