Rick Strahl's Web Log

With the betas for .NET 4.5 and Visual Studio 11 and Windows 8 shipping many people will be installing .NET 4.5 and hacking away on it. There are a number of great enhancements that are fairly transparent, but it's important to understand what .NET 4.5 actually is in terms of the CLR running on your machine.

When .NET 4.5 is installed it effectively replaces .NET 4.0 on the machine. .NET 4.0 gets overwritten by a new version of .NET 4.5 which - according to Microsoft - is supposed to be 100% backwards compatible. While 100% backwards compatible sounds great, we all know that 100% is a hard number to hit, and even the aforementioned blog post at the Microsoft site acknowledges this. But there's so much more than backwards compatibility that makes this awkward at best and confusing at worst.

What does ‘Replacement’ mean?

When you install .NET 4.5 your .NET 4.0 assemblies in the \Windows\.NET Framework\V4.0.30319 are overwritten with a new set of assemblies. You end up with overwritten assemblies as well as a bunch of new ones (like the new System.Net.Http assemblies for example). The following screen shot demonstrates system.dll on my test machine (left) running .NET 4.5 on the right and my production laptop running stock .NET 4.0 (right):

Clearly they are different files with a difference in file sizes (interesting that the 4.5 version is actually smaller).

That’s not all. If you actually query the runtime version when .NET 4.5 is installed with with Environment.Version you still get:

4.0.30319

If you open the properties of System.dll assembly in .NET 4.5 you'll also see:

Notice that the file version is also left at 4.0.xxx.

There are differences in build numbers: .NET 4.0 shows 261 and the current .NET 4.5 beta build is 17379. I suppose you can use assume a build number greater than 17000 is .NET 4.5, but that's pretty hokey to say the least.

There’s no easy or obvious way to tell whether you are running on 4.0 or 4.5 – to the application they appear to be the same runtime version. And that is what Microsoft intends here. .NET 4.5 is intended as an in-place upgrade.

Compile to 4.5 run on 4.0 – not quite!

You can compile an application for .NET 4.5 and run it on the 4.0 runtime – that is until you hit a new feature that doesn’t exist on 4.0. At which point the app bombs at runtime. Say you write some code that is mostly .NET 4.0, but only has a few of the new features of .NET 4.5 like aync/await buried deep in the bowels of the application where it only fires occasionally. .NET will happily start your application and run everything 4.0 fine, until it hits that 4.5 code – and then crash unceremoniously at runtime. Oh joy!

You can .NET 4.0 applications on .NET 4.5 of course and that should work without much fanfare.

Version Detection

If you're building a .NET 4.5 application you do have some control over the runtime via YourApp.exe.config file options. Specifically you can specify that the app requires .NET 4.5 like this (thanks for Scott Hanselman pointing this out in the comments):

This works fine for standalone applications and server, but it there's no solution for assemblies that are added to other projects. To a 4.0 project a .NET 4.5 assembly just looks like another 4.0 assembly.

For developers - especially component developers - this is also problematic since there's no built in way to determine whether you're running .NET 4.5. Environment.Version returns 4.0.

Pretty close, eh? Note however that the Revision number is high on .NET 4.5 - 17379 on the current build, while the .NET 4.0 revision number is 261. So if you really have to check specifically for .NET 4.5 you can use code like this:

Others have commented (on Hanselman's post), that it's better to do feature detection for a new feature of .NET 4.5. The code Scott used uses a new class for .NET 4.5 plus some Reflection code to check for it:

One advantage of this approach is that you're checking for a feature rather than a specific version, so in the future this code will continue to work so you effectively can future proof code.

Still it's pretty telling that we'll have to resort to this sort of chicanery just to figure out freaking version compatibility.

Different than .NET 3.0/3.5

Note that this in-place replacement is very different from the side by side installs of .NET 2.0 and 3.0/3.5 which all ran on the 2.0 version of the CLR. The two 3.x versions were basically library enhancements on top of the core .NET 2.0 runtime. Both versions ran under the .NET 2.0 runtime which wasn’t changed (other than for security patches and bug fixes) for the whole 3.x cycle. The 4.5 update instead completely replaces the .NET 4.0 runtime and leaves the actual version number set at v4.0.30319.

When you build a new project with Visual Studio 2011, you can still target .NET 4.0 or you can target .NET 4.5. But you are in effect referencing the same set of assemblies for both regardless which version you use. What's different is the compiler used to compile and link your code so compiling with .NET 4.0 gives you just the subset of the functionality that is available in .NET 4.0, but when you use the 4.5 compiler you get the full functionality of what’s actually available in the assemblies and extra libraries. It doesn’t look like you will be able to use Visual Studio 2010 to develop .NET 4.5 applications.

Good news – Bad news

Microsoft is trying hard to experiment with every possible permutation of releasing new versions of the .NET framework apparently. No two updates have been the same. Clearly updating to a full new version of .NET (ie. .NET 2.0, 4.0 and at some point 5.0 runtimes) has its own set of challenges, but doing an in-place update of the runtime and then not even providing a good way to tell which version is installed is pretty whacky even by Microsoft’s standards. Especially given that .NET 4.5 includes a fairly significant update with all the aysnc functionality baked into the runtime. Most of the IO APIs have been updated to support task based async operation which significantly affects many existing APIs.

To make things worse .NET 4.5 will be the initial version of .NET that ships with Windows 8 so it will be with us for a long time to come unless Microsoft finally decides to push .NET versions onto Windows machines as part of system upgrades (which currently doesn’t happen). This is the same story we had when Vista launched with .NET 3.0 which was a minor version that quickly was replaced by 3.5 which was more long lived and practical.

People had enough problems dealing with the confusing versioning of the 3.x versions which ran on .NET 2.0. I can’t count the amount support calls and questions I’ve fielded because people couldn’t find a .NET 3.5 entry in the IIS version dialog. The same is likely to happen with .NET 4.5. It’s all well and good when we know that .NET 4.5 is an in-place replacement, but administrators and IT folks not intimately familiar with .NET are unlikely to understand this nuance and end up thoroughly confused which version is installed.

It’s hard for me to see any upside to an in-place update and I haven’t really seen a good explanation of why this approach was decided on. Sure if the version stays the same existing assembly bindings don’t break so applications can stay running through an update. I suppose this is useful for some component vendors and strongly signed assemblies in corporate environments. But seriously, if you are going to throw .NET 4.5 into the mix, who won’t be recompiling all code and thoroughly test that code to work on .NET 4.5? A recompile requirement doesn’t seem that serious in light of a major version upgrade.

I suppose they had the ambition to release a "3.0/3.5 release", but realized they wanted to add all those new Task-based API:s into existing assemblies, rather than adding lots of System.IO.Async assemblies which would hurt later on. With there being just additions (and bug fixes) an "upgrade install" probably made sense to Redmond. Not justifying, only speculating.

Microsoft sucks at versioning, they just can't seem to wrap their heads around semver. Only Hanselman and Haacked seem to get it, which is reflected in NuGet and MVC. Recently the EF team got called out on it, and they seem to be in the process of getting their act together, recently it's simply been 4.2, 4.3 etc.

But .NET itself is a mess, let's hope they rebase at 5.0 and then get it right.

While this WILL cause all sorts of goofy problems and headaches for developers, the REAL problem here (as I see it) is that it delivers a huge NEGATIVE blow to the .NET Framework for the IT Pros and businesses (pointy-haired bosses) who will end up colliding with these 'stealth' versioning conflicts. They won't see this as an issue where Microsoft tried something new.

Instead, they'll see this as merely being a case where .NET apps are hard to support. So the next time developers want to use .NET for internal apps in companies where this was already a question of whether or not .NET made sense or not will see ADDITIONAL push-back from the folks that manage these apps.

That, and it's NOT like people didn't complain about everything you've listed here prior to them launching this silliness upon the world.

#re: .NET 4.5 is an in-place replacement for .NET 4.0 by
James
March 15, 2012 @ 9:26am

I would love to hear an explanation from Microsoft on this. Maybe Scott Guthrie can weigh in here on their reasoning.

#re: .NET 4.5 is an in-place replacement for .NET 4.0 by
John
March 23, 2012 @ 4:43am

>Clearly they are different files with a difference in file sizes (interesting that the 4.5 version is actually smaller).I think is because they get rid of the old SSE optimization code. Now SSE2 instructions are a requirement for .Net 4.5. That's why people with old Athlon XP CPU's are suffering lots of application crashes and can't open Metro apps even if they have a 2Ghz CPU that meets the Windows 8 minimum requirements.

With every new version of the .NET framework, I feel like Microsoft is taking Brad Abrams and Krzysztof Cwalina's vision of a consistent, predictable, and cohesive framework and making it so royally screwed up that they have no choice but to hit the reboot button every few years and come up with some crap like WinRT as if .NET was flawed all along.

Thanks Scott. That should help and is the behavior I would expect to be correct. I think it's more important for desktop applications than server applications I think since those go into potentially many different environments.

Not sure if you saw it but during one of the BUILD sessions (http://channel9.msdn.com/events/BUILD/BUILD2011/TOOL-834T I believe) they mentioned that the replacement was to drive some changes to the underlying CLR that they couldn't do with an additive release. Sounds like there is a big push to ensure compat which is why the product group is asking people to try the beta out.

@Colin - well to me the fact that I have to install 4.5 and wipe out 4.0 is actually the main reason I'm NOT trying it out. It's a totally intrusive install with no good way to undo short of uninstalling .NET 4.5 and 4.0 and reinstalling which in turn will break a lot of stuff that relies on .NET 4.0 - even if you immediately turn around and re-install .NET 4.5. For example, IIS apps revert to .NET 2.0 when you uninstall 4.0/4.5, and won't revert back to 4.0 when you reinstall .NET 4/5.

To your point about being able to run .NET 4.0 applications on .NET 4.5 - I found at least one issue:

I was just playing around with a annoying behaviour with the WPF datagrid that was changed on the last release of the WFP Toolkit and made it into .NET 4.0: http://wpf.codeplex.com/workitem/13022

In .NET 4.5 the behaviour has been changed to not set the SelectedItem to null when the DataGrid is disabled (yeah!)

However, now when I create a WPF application targeting .NET "4.0" the behaviour will be different depending if .NET 4.5 or .NET 4.0 is installed on the client machine... yikes! Not really 100% backward compatible.

After installing VS2011 beta my unittest fail to run, mesg: Failed to queue test run "": Unable to start the agent process. Uninstalling 4.5 en installing 4.0 fixes it for me. There is also an unpdate available for TypeMock but i could use that yet due to project constraints.

This is a critical issue if you still have an XP user base, like I do. Bugs that existed in 4.0 and are fixed in 4.5 do not show up during debugging on my Windows 7 workstation, but do when my app is run on a customer's XP box. They are not given an option to upgrade because 4.5 is not supported and I cannot repro the issue (even when targeting 4.0) on my development machine.

I do agree that the version number is confusing (expecially if your write a lot of desktop applicaiton. But for web applications I think it is a little clearer. After install installing .Net 4.0, there is not option under .Net version to run you application under ".Net 4.5", the only option is ".Net 4.0". So in reality you are running your application under .Net 4.0, just it has been updated with new functionality. So in this case if the version number was set to 4.5 and there was an option for it in IIS, then that would even be more confusing (since the options would point to the same code base, so it would not matter which you chose). I am wondering if that is why they could not update the version number from 4.0 to 4.5.

Bottom line is, if .Net 4.5 is installed then you can run apps targetting .Net 4.0 & .Net 4.5 applications otherwise you can only run apps targeting .Net 4.0. As far as backward compatibility, IMO you should always plan on regression testing all applicaiton after installing any new version of the .Net runtime. This went for 3.0 and 3.5, becuase I am pretty sure that there were some updates to a few of the core library functions that were called by the new .Net 3.0/3.5 libraries so they would work correctly with the new functions. It was not a complete upgrade of the .Net 2.0 framework like 4,5 is, but there was still the possibility (even thouhg minimal risk) that the the core changes could have broken an applicaiton that used those functions.

Tha being said, I totally agree that MS blew it on this one and they should have released this as ".Net 5.0" and have it be a side-by-side install. The main reason I think this is that an in-place replacemment upgrade makes it a harder sell when involved in an enterprise. I a also wondering how this will affect hosting companies that support .Net 4.5 and how soon they will offer .Net 4.5 as an option. I know that where I work we will probably not update any of our exsitig servers to .Net 4.5, and we will have to wait for new servers to be built with .Net 4.5 installed from the start. That way we can regression test applicaions / web services as we migrate to the new web servers.

This is - I have to say - pretty ridiculous. From the moment .Net was spoken of we all heard how "DLL Hell" would be a thing of the past due to the (sound) versioning and signing capabilities of the platform.

As Rick says every new release of the framework has followed a different "policy" and (I think) is always accompanied by confusion and uncertainty even among hardened experienced tech people.

Adding a NEW version of .Net on a machine should have zero impact on existing applications on that machine - is this now too lofty a goal?

If the specific version and build numbers are abstruse (as they are) then Microsoft should have long ago created a utility "FrameworkInfo" that can list and shed light on EVERY version of .Net installed on a machine - this would help humans see what are .Net 4.5 and .Net 4.0 assemblies for example.

There are issues with all this - apart form the bewildering 4.5/4.0 mess there is also the fact that a) AppDomains often (always?) load TWO copies of every assembly and b) There are at least TWO physical copies of every .Net assembly on a machine (one in the GAC and the other in an ordinary folder - seen by VS when you use 'add reference').

Great post!, but when you say "You can .NET 4.0 applications on .NET 4.5 of course and that should work without much fanfare."

I'm not totally agree, because I have an application compiled with 4.0 framework and now for an incompatibility issue with IE11 following the microsoft suggestion I upgraded to 4.5 framework in order to solve the problem, but now sometimes my application crash unceremoniously at runtime. Now I'm trying to solve that :P

I am using West-wind SQL resource provider in asp.net with framewrok 4.5.1.
I added it using NuGet package. When i click "Generate Local Resource" in "Tool" menu, it gives "Object reference not set to an instance of an object".
Manually created resource file works, but is not generating resource automatically.
Can anybody suggest what is wrong with it or from where i can download latest resource provider DLLs without Nuget which support 4.5.1 framework?

Nice that one can require a specific verision in YourApp.exe.config. Just wondering: how is this piece of xml information evaluated? What piece of information is consulted to decide wether or not it is 4.5? Is it the registry entry "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SKUs\"?

Windows 10 Tech Preview build 9860 returns 4.0.30319.0 from Environment.Version. This means any version detection used in code is going to fail if you need the revision #. For example, I can't run Sharp Develop 5.0 RC because of this. See screenshot: http://i.imgur.com/S8ai4IZ.png

As much as I like doing c# and .net tech, .NET 4.5 is causing major headaches in our web application projects, mainly asp.net mvc.

Some of our backend libs still are 4.0 since they're mainly used in WinForms applications where we don't want to force the clients to do a new download.

But as good as it is, Visual Studio 2013 is a pain, when using asp.net MVC and you do NOT want to use 4.5, especially if you're using nuget for all those nifty packages like bootstrap, jquery, log4net etc.

I sometimes don't understand why the VS and .NET teams don't have the Developers in mind, who are actually using their stuff. I would like to keep costs low, but I'm wasting my companies money on such issues.