Scott Hanselman

.NET Versioning and Multi-Targeting - .NET 4.5 is an in-place upgrade to .NET 4.0

April 03, 2012 Comment on this post [89] Posted in Learning .NET
Sponsored By

Say what you will about the past ridiculousness of .NET Framework versioning, since the confusion of .NET 3.5SP1 they've  been trying to get it right. It's not the magic of Java Version 6 Update 31 (build 1.6.0_31-b05) but it's a start. O_o

Back in July of 2011 I wrote a post on Issues with .NET and Microsoft Product Versioning that got the attention of some folks. I was most concerned about some "platform updates" to .NET 4 and the way they were named. Meetings were had and those small updates now have simpler names versions like NET 4.0.1, etc.

I'm not going to tell you it's not confusing today. I do think that things are getting better and becoming less confusing. .NET 4.5 is a step in the right direction of transparency in versioning.

The .NET Framework can version in two ways. There are "side by side installs" and there are "in place upgrades." A major version means side-by-side and a minor version means in-place.

Side-by-side means that different versions of .NET can live together on the same machine.

Diagram: .NET CLRs can live side by side

In-place upgrade means that the CLR is the same but new libraries are added as well as bug fixes and performance improvements:

Diagram: .NET 4.5 builds on top of .NET 4

There's been some concern about how .NET 4.5 is an "in-place upgrade" of .NET 4. That means .NET 4.5 is still the v4CLR and adds new libraries as well as improvements to the core CLR itself.

Rick Strahl said on his blog:

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.

Rick has a great post with a lot of detail and information. However, respectfully, I don't think .NET 4.5 vs. .NET 4 is as different as Rick implies. In fact .NET 3 and .NET 3.5 both upgraded the system (and CLR) in place as well.

Perhaps if 3 and 3.5 were called .NET 2.5 and .NET 2.8 it would have made more sense. The community is always concerned about breaking changes, much like we are here with .NET 4 and .NET 4.5. Unfortunately reality and marketing names haven't always matched, but going forward I think we all agree that:

  • Major Version = New CLR
  • Minor Version = Bug fixes, new libraries
  • Revision = Bug fixes, no breaking changes, small improvements

.NET 4.5 is not a radically different side-by-side CLR. A new CLR would be a theoretical .NET 5 In my opinion.

Could something break with .NET 4.5? This is why it's in beta now, so now is the time to speak up. It's possible something could break but unlikely according the .NET Blog. Here are the known .NET 4.5 breaking changes - most are pretty obscure. The kinds of breaking changes I've seen myself in the wild have been primarily when folks are relying on reflection or internal data structures. These internals aren't public contracts so they may have changed. I realize that when a change breaks YOU it feels like a situation when "100% of applications will break....mine did!" situation. It sucks, but in fact there are minimal breaking changes in .NET 4.5.

Can I get .NET 2.0, 3.5, 4 and 4.5 apps all running together on my system? Yes.

Can I develop apps with different versions with Visual Studio 11 Beta? Sure, you can multi-target all these versions and even plugin more targeting packs. I'll do a blog post later this week on Portable Libraries, a new version in .NET 4.5 that makes creating libraries for any CLR (including Xbox, Phone, Mono and others).

Screenshot of the multi-targeting dropdown in Visual Studio

Developing Safely for both .NET 4 and .NET 4.5

It's been implied on blogs that if you install .NET 4.5 on your machine that you can't safely develop for .NET 4. In Rick's post, he compares two DLLs on a .NET 4 machine and again after the .NET 4.5 in place upgrade. How can you target safely against .NET 4 if you've installed .NET 4.5? You don't have those .NET 4 DLLs anymore, right?

Actually you do. They are in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework.

Reference Assemblies

Let's prove it on a machine with Visual Studio 11 Beta. I'll make a DLL and reference System.Web and make use of one of the added types in that assembly. Yes, it's a screenshot of code, but hang in there.

Using the .NET 4.5 ModelBinderDictonary Type

Now I'll change the properties of my project from .NET 4.5 to .NET 4. I won't change anything else. I'll build. Note that the type isn't there, I get a build error and I can't reference the namespace. You will know if you're using new .NET 4.5 functionality. The multi-targeting build system was designed for this and existed as far back as .NET 3.5. Those reference assemblies are there to catch this kind of thing.

Referencing .NET 4 and using a type we don't have will cause a compiler error

So while .NET 4 and .NET 4.5 don't live side by side on your system at runtime, Visual Studio knows about all the different versions of .NET and the compiler will reference different versions when you build.

If you are making a client app, like WinForms, Console, WPF, etc, this is all automatic. Your app.config contains that fact that you need .NET 4.5 and you'll even get a prompt to install it.

<?xml version="1.0" encoding="utf-8" ?>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />

So if I run my .NET 4.5 Console App on a .NET 4.0 machine now I get a nice dialog.

A dialog that pops up when running .NET 4.5 apps on .NET 4 to prompt an update

Looks like this technique doesn't work on ASP.NET (I would expect a Yellow Screen of Death)...I will talk to the team about that. I think this is a good thing and ASP.NET should respect it also.

UPDATE #2: The system will throw an error when an ASP.NET 4.5 application is deployed to an ASP.NET 4 system. The default templates on for ASP.NET 4.5 applications include the targetFramework attribute set to 4.5 like this:

<compilation debug="true" strict="false" explicit="true" targetFramework="4.5" />

This will throw a YSOD if you deploy a 4.5 to a 4 machine like this: "The 'targetFramework' attribute currently references a version that is later than the installed version of the .NET Framework."

UPDATE: If you really, really want to detect .NET 4.5 at runtime, don't check versions or build numbers. Check for the existence of the feature you want to use. For example, from this Stackoverflow question by Christian K, here's how to detect .NET 4.5 programmatically.

However, David from the CLR team (in the comments) says that this is not a good idea. He says to check if an important feature is there and use it. Don't cheat and infer .NET versions.

"The IsNet45OrHigher example is not what we'd recommend. By feature detection, we mean 'detecting the presence of a feature before you use that feature', <i>not</i> 'using the presence of a feature to determine what version of .NET you are runnning on."

public static bool IsNet45OrNewer()
// Class "ReflectionContext" exists from .NET 4.5 onwards.
return Type.GetType("System.Reflection.ReflectionContext", false) != null;

Microsoft has said the same thing about Operating System features:

Identifying the current operating system is usually not the best way to determine whether a particular operating system feature is present. This is because the operating system may have had new features added in a redistributable DLL. Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself.

Related Posts

Sponsor: My sincere thanks to Axosoft for sponsoring this week's feed! Imagine agile project management software that is brilliantly easy to use, blazingly fast, totally customizable, and just $7 per user. With OnTime Scrum, you won't have to imagine. Get started free.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
April 03, 2012 0:35
Really appreciate this being resolved and explained!
April 03, 2012 0:45
Ok, so if they're so similar, why can't I install it on Windows Server 2003? I was very frustrated when I went to do so on a client's server and found it wasn't supported. Is this a temporary thing? Will the final release support 2003?

April 03, 2012 0:54
I'm still wary of Ricks comments under "Compile to 4.5 run on 4.0 – not quite!".
Target an app for 4.5, use some 4.5 features, then run the app on a machine with only 4.0 installed. It happily plugs along until it gets to the 4.5 features, then fails.

If this is the case (I haven't verified it myself), then we've still got confusion over "do I have the right version installed?"
April 03, 2012 1:02
Why increment directly to .5? If we're going to talk about how it would have been simpler, it should have been:
* 2.0 => 2.0
* 3.0 => 2.1
* 3.5 => 2.2
* 4.0 => 4.0 (or 3.0, but I'll call it 4 to keep it understandable)
* 4.5 => 4.1

There's another problem though. I have a product that targets .NET 2.0, but unfortunately requires a bug fix contained in SP2. This crazy versioning means we can't just say "Requires .NET 2.0 SP2 or higher", because 3.0 also has the bug. We have to actually say: "Requires .NET 2.0 SP2, 3.0 SP2, 3.5 SP1, or 4.0 or higher". Yes, really.

If it was 100% up to me, the requirements would just be .NET 4, but I'm told that our customers don't like us requiring them to upgrade the .NET framework (this was apparently a big issue when we upgraded from 1.1 to 2.0). I'm pretty sure these are the same people that stuck with IE6 because it's "more secure" (and maybe still do), but we have to deal with them all the same.
April 03, 2012 1:03
This is pretty interesting. Does this mean if I have .net 4.5 installed on my machine my .NET 4 targeted applications get the performance improvements to the core libraries implemented in .NET 4.5?
April 03, 2012 1:10
Luke - Yes, .NET 4 apps get the CLR and library improvements when run on a .NET 4.5 system.

Gregmac - Yes, that would have made more sense, although 2.1 seems like a small change. Still, point taken.

JasonB - Yes, maybe I can make a "am I running on a .NET 4.5 machine" function that we could use to *fail fast.*

John - I don't know, but MSDN says it doesn't support Windows Server 2003. It's possible because Windows Server 2003 is coming up on 10 years old.
April 03, 2012 1:12
@Scott - Awesome. Your article and Rick's help clarify things quite a bit. I forwarded it to our entire team as they are often concerned about breaking changes with the small (.5) releases.

@Luke - I'd only trust Scott for certain, but I'm thinking 'no'; if you target 4.0, you will be targetting the original runtime, and thus won't get what improvements bundled in the new 4.5 dll. I'd also guess that you wouldn't get to use new libraries in 4.5 as they likely depend on that new runtime. Overall I think it is to pacify the worry that a .5 version doesn't mean you have the new runtime forced down your throat if you are really really really concerned.
April 03, 2012 1:13
@Scott & Luke - Bad guess, sorry. How does one get the benefits in the new DLL if you are targetting the original?
April 03, 2012 1:22
@Scott that's really interesting, I have been doing some benchmarking on EF4 vs EF5 and I tried running my tests when built for .NET 4 and didn't get that different results, but from what I've read many EF5 improvements have been made inside of the .NET 4.5 runtime. I think this explains my results here :)
April 03, 2012 1:27
A bit of a tangentially related question, but I'm curious to know how Microsoft generates those reference assemblies. I talked to someone at //build about it, and searched around on Stack Overflow, but I have yet to be able to figure out how to generate something similar on my own.
April 03, 2012 1:31
Trey - Targeting a DLL at build time makes sure that methods and metadata lines up. The "reference assemblies" are for referencing at build time. When you run your app it runs against the main DLLs in the GAC.

Daniel - Not 100% why you'd want to but you add the ReferenceAssembly attribute.
April 03, 2012 1:32
I'm hoping this isn't too naïve:

Aren't breaking changes, at least compile-time breaking changes, deterministic?

As long as all of the existing objects and members with the same signatures still exist, then additional objects and members shouldn't matter, right?

What other breaking changes would we be looking for?
April 03, 2012 1:37
Brianry - Subtle behavioral changes. Usually when someone relies on a bug's wrong behavior and the bug is fixed.
April 03, 2012 1:41
@Scott: Gotcha. Runtime stuff with no guarantees in the first place. ;)
April 03, 2012 1:42
The biggest issue in my mind is the scenario of:

* Compiling to .NET 4.5
* Running on a system that only has .NET 4.0

and then not having an easy built-in way to check whether version 4.5 is available.

If I run the 4.5 app on 4.0 it'll bonk at runtime and that frankly sucks big time.

Looking at the version numbers it seems that we can *hopefully* look at the CLR versions build number.
April 03, 2012 1:44
@Scott - Thanks. I did understand the reference assemblies role at build-time; our department learned that well when first using Oracle's ODP.Net assemblies and then finding that different ones were being used on deployment machines. I thought you were explaining that the original runtime was still targetable on deployed machines.

So...I can target 4.0 for building, but then when deployed to a users machine it will always use the updated 4.5 dll (if installed)? Am I understanding correctly?
April 03, 2012 1:48
@Rick *nod* one of the nice things about web apps, no? maintaining the runtime in one place :)
April 03, 2012 2:00
Trey - Yes. A targeted 4.0 app will use .NET 4.5 if it's installed. Just like opening a Word 2003 doc will run Word 2010 if installed.
April 03, 2012 2:29
.NET Framework source stepping is broken for .NET 4.0 applications when you install .NET 4.5, whether you are trying to use VS2010 or VS11 Beta, because the assembly versions and symbols no longer match up.
April 03, 2012 2:36
Richard - I'm talking to the team about that now.
April 03, 2012 2:41
Rick: Simply drop the config created at new project time alongside your application, and the runtime will do the right thing (ie popup up a dialog telling you need to install a later version of the framework).

Scott: The IsNet45OrHigher example is not what we'd recommend. By feature detection, we mean 'detecting the presence of a feature before you use that feature', not 'using the presence of a feature to determine what version of .NET you are runnning on.'
April 03, 2012 2:49
@Scott: DevDiv triage says that it's expected because it's a beta and they don't ship beta source, but the problem is that it breaks VS2010, which should definitely be a no-no.
April 03, 2012 3:56
It's too late, but since MS is in the "componentization" move, the CLR/BCL parts should have been splitted.

- CLR updates via WU
- BCL as NuGet packages

WinRT smells like a cleaned version of .NET framework dependencies, alas we have no idea of was versionning sheme will apply. (and since we are back in the .NET/COM interop horror era, i really wonder how a developer will handle sxs development of metro apps)
April 03, 2012 4:52
I look forward to your blog post later this week about the Portable Library Tools. Particularly, the comment about supporting Mono; additional support for non-Microsoft CLRs seemed to be on the table when the Portable Library Tools were released but, as far as I have seen, progress in this direction hasn't advanced.

I would LOVE to be able to mark a project in Visual Studio as being a Portable Library targeting WP7, and Xamarin's MonoTouch & MonoDroid. Then I could at least develop some of my mobile apps (other than WP7 ones), ie. any network or model code that is independent of the mobile OS UI framework; in Visual Studio, and continue the rest of the development in MonoDevelop (which is great, but still behind VS + Resharper in productivity terms for me).
April 03, 2012 5:46
Unfortunately 4.5 isn't entirely compatible with applications compiled against 4.0. An application I built that uses last year's DevExpress components fails to run once .NET 4.5 is installed. WebMatrix beta which ran fine on 4.0 began crashing once 4.5 was installed. Yes, the next Webmatrix refresh fixed this. But the point is, it may not always be possible or practical to re-compile an application to accomodate a new framework that the application doesn't even care about. And in the case of a third party component that stops working with 4.5, there's no guarantee they will update it to work.

That was supposed to be one of the great things about .NET. The side-by-side versioning meant that the CLR and framework I built against would be used at runtime. .NET 3 and 3.5 flirted with breaking that promise but since it made minimal changes to the runtime and framework, it didn't create a major burden. But hard disk space is practically free and we already know the runtime selection code works so why mess with that? What advantage is there to making 4.5 replace 4.0?
April 03, 2012 7:07
such a web, web, web, web world. At BUILD.. they said 4.5 would only be on Win8 and above. Can I take a .NET 4 Winforms app and compile it with 4.5? and run it on Win7? (gasp.. XP?) .. is it side by side if it doesn't work on OS'es that 4 works on now?
April 03, 2012 9:12
Life's gotten a lot better over the years with the SxS story and clearer messaging around what's being serviced by a particular major update. Still, I find it inexcusable that there's still no built-in API for discovering which version you're running on (including all servicing). We've had several cases over the years where our code would break hard without a given hotfix or patch level. Aaron Stebner's detection sample works for the major/minor version and service packs, but there's no simple way I'm aware of to simply and reliably detect the presence of a given hotfix that only changes behavior (not metadata). I'd love it if we could look them up by KB number (so they'd "stick" with SPs).
April 03, 2012 11:51
Sorry, but this is all very confusing still.
April 03, 2012 12:31
Hey Scott,

there is a little bit confusion if the final .NET Framework 4.5 will support Windows XP as for the Beta there is no Support for it (and also not for Vista).

For an "in place upgrade" which also contains bug fixes I would expect the same supported operation systems as for 4.0 but since now there wasn't any announcment. Do you have an idea if XP is really dropped?

Kind regards,
April 03, 2012 13:28
@Scott - Awesome: I like the idea to add <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> into app.config for almost any app type, EXCEPT ASP.NET if your app require .NET 4.5 runtime. It's not exactly detection, however :(... Anyway, my +1 to ask ASP.NET team if they can add support for such configuration parameter too.

Btw - I add reference to your post on related stack-overflow question (
April 03, 2012 13:32
This is a disaster of similar proportions to .Net 3.5 SP1 and I can't believe you can't see it.

Why oh why is .Net 4.5 including BOTH new features AND updates to 4.0 while masquerading as 4.0 vanilla?

This should either be {Framework 5.0} or {Framework 4.0.1 AND Framework 4.5}.
April 03, 2012 15:24
Scott - A question that is somewhat related to the versions and Visual Studio 11.

Previously we found when we upgraded to 2010 that a number of cool features were disabled for .NET 2.0 such as code coverage analysis & code impact analysis and you had to be targetting .NET 3.5 even though it was the same CLR.

Do you know if there are similar restrictions in Visual Studio 11? Do I need to be targetting .NET 4.5 for the latest and greatest features or will they work for some of the slightly older versions?
April 03, 2012 15:28
I know of an issue caused within StructureMap which is due to changes in reflection you mention. However, there is no mention of reflection at all on the page: Application Compatibility in the .NET Framework 4.5 Beta. This does make me slightly nervous. Is this on Microsoft's radar in that it at least provides info on necessary changes to be undertaken in your own codebase?
April 03, 2012 16:33
Now if only we could get some compact framework love!
April 03, 2012 16:38
Sorry, but I can point to 2 separate cases we've already had where V4 compiled web sites fail with .NET 4.5 installed on the server (and still set to target V4). Thus I would strongly suggest that not only can you not safely run V4 stuff on .net 4.5, you can't safely have .NET 4.5 installed at all because it alters behaviors of everything .NET on the machine.

1. This used to be the default in the web.config implicitly: <modules runAllManagedModulesForAllRequests="true" /> You didn't have to set it. .NET V4 would just work because it was the default. .NET 4.5 changes this behavior FOR ALL SITES RUNNING .NET 4.0 OR LATER unless explicitly set in the web.config file. Thus if you don't manually set this on every site before you upgrade to .NET 4.5 they will break if you use handlers on file types that .NET recognizes (i.e. .aspx, .png, etc.)

2. .NET 4.5 changes the behavior of ALL .NET 4.0 AND LATER sites as soon as it's installed so that previous structures for dynamically loading and executing assemblies with reflection that worked in .NET 4.0 will fail causing bugs in your previously working code. The only known work around is to change your source to use the new way instead of the old way that worked for 5 previous versions of .NET just fine, compile and update those sites.

As a shared web provider, this makes .NET 4.5 almost impossible to install on anything other than new installations with sites that are explicitly designed for .NET 4.5. And #2 also affects Winforms and console applications as well, so as it stands right now, anyone installing .NET 4.5 could as a result crash any .NET 4.0 fully standards compliant application that happens to be installed on their machine.

So no, .NET 4.5 is not an inplace upgrade. It's an inplace, better have your patches ready and know what's going to break before you deploy it, and be very scared if you deploy a client application with it, because it could break 3rd party apps-upgrade.

So Scott, and everyone else at MS: Let's be real about this. It isn't what you say. You either need to make it side by side like we were originally promised where every new version of the .net framework was going to be it's own install and completely independent of previous versions and NOT inplace. Or you need to fix these numerous upgrade issues (I'm seeing tons of them in the comments above mine that are different and even worse!) and make it a truly inplace upgrade. I prefer you do what you promised you were going to do with .NET 1.0 and make every single one of them side by side with absolutely no alteration of the previous version. Disk space is plentiful, don't create dll hell part 3 for no reason.
April 03, 2012 17:42
It's the same for Javascript and browsers. Don't check the version of the browser but check if the feature is available. Ex.: The offline storage.
Good article.
April 03, 2012 18:07
For my project installing 4.5 crashed the site because our custom WCF ServiceHostFactory now gets the http/https bindings in a different set than before. Unfortunately I had no time to investigate and fix/workaround it so all our .NET devs have received an e-mail prohibiting them from installing 4.5 outside of virtual machine...

The comments above and on other threads confirm that this was the correct choice since there is no guarantee that another bug will not jump out later on.

But I do hope that many of these issues will be fixed in RTM.
April 03, 2012 18:31
I am sorry but there is no compelling reason why it can't be a side by side installation.
April 03, 2012 19:28

2 issues you've touched on here where Microsoft really seems to have dropped the ball big time.

If Microsoft would have done the logical thing and made the APIs the same, they wouldn't need the shim/kludge that is the multi-targeting stuff. There should be no more than 2 APIs, full (desktop/server) and mobile (Silverlight, Metro, Phone), and mobile should be a strict subset (in other words, everything in mobile should be in full, and with identical classes & namespaces). Big time WTF making so many divergent platforms and then telling developers to target the least common denominator. (Yes, the shim allows the craziness about 4.0 and 4.5 having the same version number, but even here the confusion of the kludge should have outweighted the advantage of having only 1 set of assemblies on a client... if you believe it's an advantage, which I don't--I'm with Rick Strahl on that one--it opens the door for bugs that should be impossible without assembly forwarding in the config file.)

Also, on version numbers, add-ons to .NET should have identical version numbers to the version of .NET that they target, and the 4th part of the build number should be the only thing that changes if there are multiple versions of the add-on targeting the same framework. After EF jumped version numbers to sync up, they've now diverted again, numbering their release for .NET 4.5 as v5 instead of v4.5. It's a HUGE mistake, and not correcting it is going to compound that mistake over and over again. And Microsoft not firing the person responsible for the decision is an unforgivable slap in the face to the entire .NET dev community.
April 03, 2012 19:42
We're upset that one of our apps crashes as soon as 4.5 is installed.

Instead of being able to say "you must have .net 4.0 installed" to run our app, we have to say "you must have .net 4.0 installed and never install 4.5. Don't run windows update, please!". What kind of message is that?

Unfortunately, a new product is being written against 4.5.... so that means we need to pick one:

* take precious developers off the new product and put them on our old (working, released) product to fix issues with 4.5 installed. Do full regression testing on the product despite no functionality changes by us (expensive!)

* tell our customers that they can't run both the new product and old on the same computer (and please don't run windows update on the computers with the old product)

* switch to a different language? live in a cave and wear hair shirts?

This very much loses the "no compat issues because of SxS installs" advantage we thought .net had. Ouch!
April 03, 2012 20:23
For me installing 4.5 definitely broke the web installer which relies on 4.0.
April 03, 2012 21:18
I think this article was actually very helpful. It does not provide a fix for everyones special case but I don't think that was the point. I think it was more of a clarification of where the .Net framework is going.

In terms of Asp.Net supporting the "SupportedRuntime" in the config. I think that is great if it could, but it would really be to handle edge cases for Asp.Net as the IIS settings (AppPool or Asp.Net settings) would be where you set the .Net framework target. I would assume that installing .Net 4.5 would add another framework choice to this list too (aspnet_regiis).

As to in code determination of what .Net framework is installed, this should also be an edge case as most applications have an installer. Typically the install checks for prerequisites and notifies users if they are missing or installs them if missing.
April 03, 2012 21:45
"This is a disaster of similar proportions to .Net 3.5 SP1 and I can't believe you can't see it."

"there is no compelling reason why it can't be a side by side installation."


Scott, respectfully, I'll stick with the experiences shared by the guy out there deploying solutions. It's painfully obvious you've left the trenches... I hope you keep up with the comments on Rick's blog post too.
April 03, 2012 22:19
Jed - I was in the trenches nigh twenty years. I've left already, in this little time? Built some stuff out there too.

Nicholas - Details so I can see if it's fixed? It is a beta.

Philip - Same, I need details to see if I can help.

Knaģis - I'm passing your info onto the WCF team to see if that's a bug.

Matt Davis - I agree. I'm trying to get clarity on that from the CLR folks.
April 03, 2012 22:42
Everyone who has to deploy software: "side by side + easily detectable, please!"

Scott: jazz hands aka "Visual Studio is a big enough band-aid"

It's understandable from both sides, and it's clear which side you've come down on so far... I think what's needed is to publicize what must be the ridiculously compelling list of reasons things won't be side-by-side even when there are clearly breaking changes.

I appreciate what you're doing inside Microsoft but this post rings hollow because it sounds like for the most part you're taking the .NET team's word for it rather than deploying real-world applications.
April 03, 2012 22:50
Also want to be clear that I see this as another chance for you to stand up for developers as you have been doing such a great job of so far... from your Semantic Versioning post: "I've met with that team, and encouraged them to stick with Semantic Versioning and call these updates .NET 4.0.2, etc."

I interpret points 4, 7, 8, and 9 at quite differently from your "think we all agree that" where you allow a lot more wiggle room for the marketing department.
April 03, 2012 22:55
Jed - My side is always the customer's side. I didn't need to write this post, I don't even work for that team. I'm just trying to explain it.

I'm sorry if it 'rings hollow.' I am continuing to push what I believe is the correct path with the teams that will listen to me. I'm not a VP or in charge of something so I can't just TELL folks what to do as much as I'd like to. I'm the voice of the customer on the inside and I will continue to be your advocate.

April 03, 2012 23:23
@Scott - I don't expect you to fix the issue (we've already sent an email to support on the WCF issue we've found, and we're trying to isolate the change in WPF's combobox where setting a filter in the ICollectionView re-fires either SelectedItemChanged or ListDataChanged)

The bigger issue is that now that we know that there are behavioral changes, we have to do full testing - not all of which is automated.

So if you'd like to help me, don't worry about the specific change. Instead, convince a VP or someone in charge that breaking changes *break things*. Fix it for ".Net 4.5 SP2 update rollup 3 hotfix 325829". The windows team goes insane trying to make sure apps that worked in windows 95 continue to work in windows 8 - why punish us for writing the application in .net?

Saying, "your .net app will work on any computer that has .net 4 installed, regardless of OS." is great - until there's multiple incompatible versions of ".net 4" that are mutually exclusive.

April 03, 2012 23:24
Thanks much for your efforts; I definitely don't want to discourage them! It is disappointing to realize that these types of changes take time.

My hypothetical blog post on this would start "I disagree with the .NET team's decision to move forward with another in-place upgrade that is on track to go over as well as .NET 3.5 SP1, but since we're stuck with it now, here's the best we can do to make sure it doesn't cause us too many problems..."

I would encourage you to track down any and every possible justification for this decision... people are typically more understanding when they have a chance to see something as the lesser of several evils rather than "this is the way it will be."

Keep up the good work.
April 04, 2012 0:04
Philip - Ok, let me know. One thing I must point out (and this is not Microsoft specific) is that the LARGE majority of breaking changes in any framework are fixing bugs. Folks build systems that use reflection, work-arounds, and/or generally rely on broken behavior. When that's fixed, it goes back. I'm NOT saying that's what you're doing but I'm just pointing out that 99 out of 100 changes are bug fixes.

Jed - Thanks for understanding. I hear you.
April 04, 2012 2:12
"The IsNet45OrHigher example is not what we'd recommend. By feature detection, we mean 'detecting the presence of a feature before you use that feature', not 'using the presence of a feature to determine what version of .NET you are runnning on."

This is terrible. I write for the .NET framework because I expect the compiler to let me know that all types/methods that I use are available and valid. If I can't even depend on features being available at compile time, what's the point? I might as well switch to an entirely duck typed language if I'm gonna have to resort to using reflection to figure out if I can or can't do something based on the installed framework.
April 04, 2012 12:35
I guess I just don't understand the point of this Framework 4.5. As far as I can see it does the following:

i) Makes breaking changes to the core 4.0 CLR, while not incrementing the version number
ii) Adds new libraries (additional assemblies that are compiled against Framework 4.0)
iii) Introduces new compilers that contain syntactic sugar for ii)
iv) Releases in-band with VS2012 with updated intellisense for iii)

Point i) is horrible and puts .Net into the area of Java-style "versioning" where a large number of machines are stuck on an old version of the JRE (I'm looking at you, Cisco Management Tools) because "security fixes" break existing apps.

The remaining points describe addons to the existing Framework and it baffles me that at the same time as the ASP.Net team are pushing componentisation and NuGet the Core Framework team are trying to turn additional components into entirely new frameworks.
April 04, 2012 22:16
"I am continuing to push what I believe is the correct path with the teams that will listen to me. I'm not a VP or in charge of something so I can't just TELL folks what to do as much as I'd like to. I'm the voice of the customer on the inside and I will continue to be your advocate."

I can understand this position from previous work experience, thanks for trying.
April 05, 2012 12:53
I think there is still one question which hasn't been clearly answered yet: WHY? What was the motivation for breaking one of the most significant .NET features? IMHO this is bringing DLL HELL back to developer life. The only reason I see between lines is that Windows 8 need this = Microsoft need this but that is not something customers will accept.
April 05, 2012 19:16
Found an example of the lengths even teams within Microsoft are having to go to to "properly" support all the changes / portable library stuff:
April 05, 2012 20:47
If you release this with all of these breaks in functionality that no longer worked the way they did in .net 4 you're going to have a support nightmare on your hands.

Especially with client stuff. Winforms apps are going to be busted just by the machine getting .NET 4.5 in a ton of cases.

I hope you guys fix your broken stuff and make .NET 4.0 in .NET 4.5 (see how silly that is saying that???) actually behave like .NET 4.0 IN .NET 4.0. Cause the way it is right now is a disaster.
April 05, 2012 21:14
James - The CLR and .NET teams are watching this thread and are interested in ANY breaks and repros that you guys can share. This IS an extremely compatible release I think that this "breaking changes" thing is getting a little blown out of proportion. (This isn't directed at you, James, just generally). The reason we have beta is to find issues.

There's a few kinds of potential breaking changes as I see it when you're making a framework.

- Some internal private implementation change and an app that was digging around with reflection broke. They shouldn't have been doing that. That's net specific to .NET. I was doing direct screen memory access on the Palm Pilot 20 years ago and it broke with a release one day. They moved an internal.

- An actual bug fix where some totally incorrect behavior was fixed and an existing application was relying on incorrect behavior. That's a tricky one that the team has to look at on a case by case basis. I won't presume to speak for the .NET team. They will speak to that good question in an upcoming post on their own blog.

- An inadvertent breaking change. This is the one that I'm personally most interested in. If you have a .NET 4 app that breaks when you install .NET 4.5 then I/we/them want to hear about it.

But to be clear, .NET 4.5 should have minimal breaking changes. The team has said that want to chase down any repros that you can give them.

It's too early to panic. That's why there is a beta. Let me know, or even better, the .NET team is actively monitoring the .NET vNext Framework Forums. Either way I'll see that they get your bug report.

Expect to see a detailed blog post from the .NET framework team some time next week.
April 09, 2012 3:27
Hey guys,
For those interested; I just released a new version of .NET Version Detector.
It now supports .NET 4.5 / Windows 8.
Go to the website
April 10, 2012 1:16
Thanks for the updates on the .config checking Scott.
May 01, 2012 18:31
An example in the first comment on this blog of how .NET 4.5 overwriting .NET 4 breaks an application even with Visual Studio 11 trying to help out:
May 23, 2012 21:48
I found there is a behaviour change in the WPF DataGrid. When I run an existing application compiled against 4.0 setting DataGrid.IsEnabled = false also sets SelectedItem = null. However, when I run it on a machine with 4.5 installed SelectedItem is not set to null. May seem like a minor issue but it completely changes the expected behaviour and could lead to broken applications.
June 02, 2012 8:28

You have touched on the real problem with the in-place upgrade:

"the LARGE majority of breaking changes in any framework are fixing bugs."

You assume that I am happy to have these bugs fixed when I developing "Targeting .NET 4.0".

But I NEED to see them. I need them to break while I am debugging so I can workaround them (or postpone the related features).

Here is an example that explains this:

A WPF developer creates an application using the new Visual Studio 2012 (which requires .NET 4.5).  The developer targets the application to .NET 4.0 (because his company still has a lot of Windows XP machines).

During development an ObservableCollection is bound, grouped and sorted.  The developer does not realize that this causes a severe bug in .NET 4.0.  And since since .NET 4.5 is installed on his development machine, this bug will not show up during his debugging.

When the application is released, it will fail when run on a Windows XP machine (because XP it cannot run .NET 4.5).

The bugs fixed by .NET 4.5 ARE the problem.

Because unless I know and watch out for all of them (and Microsoft will not post a bug fix list) then I can't know that I am not having bugs hidden from me by .NET 4.5.

These hidden bugs are the real problem of the in-place upgrade. The problem no one will talk about.

Please tell me I am wrong. That there is a way to install .NET 4.5 and Visual Studio 2012 and still develop and debug apps to run on .NET 4.0. I hope there is. But I bet there is not.

So my options are to:

1. Ban .NET 4.5 from my company.

2. Try and set every developer up with a Windows XP box to remote debug on (and hope and pray that they follow that practice (not likely))

3. Add an extra layer of Windows XP Compatability testing and hope that it catches everything (think of all the checks you do while debugging and think if any post development testing step will really replace that.)

None of these are good options. But even though I want to go with #2, my management is telling me that they will choose #1.

While I don't like it, I am grateful we realized it before we went and upgraded all our developers and started seeing bugs in production.

I anticipate the "Target .NET 4.0" feature will really catch a lot enterprises off guard and cause some production downtimes.

June 14, 2012 20:46

Just to add on to Schaff's post, I just downloaded the sample project from that Connect item and opened it in VS11 beta.

IRRESPECTIVE of what the target version was, the code worked, so it is evidently NOT using the 4.0 assemblies, but is using the 4.5 ones, even if you target 4.0.

How does that fit with what you wrote?
June 14, 2012 21:56
Just to follow up for anyone interested, I found out that what Scott showed worked because he was using a new feature in 4.5, so when he tried to reference it from a 4.0 project, it gave an error.

However, this does NOT prove that the project uses 4.0 assemblies. In fact changing the target version only changes the reference assemblies that are used, but these only contain the public method signatures, NOT the implementation. So, if you install 4.5 on your machine, you'll get both sets of reference assemblies, but irrespective of which version you target, THE SAME ACTUAL IMPLEMENTATION WILL BE USED.

This is a major disaster, as Schaff pointed out.
August 27, 2012 19:37
I experienced an issue after installing VS2012 and .Net 4.5 because of this in-place upgrade.

Even though my app still targets the .Net Framework 4 and not 4.5, I was able to use MEF to export using generics, which was added in 4.5. This compiles and runs on a machine with 4.5. It compiles on a machine with 4.0 but fails at runtime. This lead to me deploying code to users that only runs on my machine since they do not have 4.5 yet. They get a runtime error since the part could not be found. I would have expected that if I target 4.0 that I cannot make use of 4.5 features and would get a compiler error or at least the same runtime error that my users and other devs on 4.0 get.

I opened a bug in connect:
September 16, 2012 5:12
I know this is an old post, but even after RTM there are bugs introduced by 4.5 that pop-up (they're all in Connect, so no point in posting them here).

The point, however, is that the trust is lost. I used to think that installing a new version of the .NET framework was perfectly fine since it was adding and not changing anything. Now we have to choose between breaking existing 4.0 apps or using 4.5.

This was a very bad decision.
October 04, 2012 15:45
I concur with Peter.

We have just identified 2 vendor systems which break under .net 4.5 - I have no control over that code and no way to force the vendor to fix their code - so we now have to embargo the deployment of .net 4.5 / Windows 8 in my organization. This feels like DLL Hell all over again, making breaking changes to DLLs, keeping version numbers the same - don't Msft learn anything ?

I appreciate Scotts explanation , but the reality on the streets is that stuff is breaking - up until now Msft have done a great job of side-by-side with .net.
October 10, 2012 0:24
NOOOOOOOOOOOOO! I just finished fixing some old SL4 code because installing SL5 broke some controls from Telerik in my case. And I thought to myself, sure glad the rest of .net doesn't work like that. :)

There is a well know similar problem with Internet Explorer 6.0 & 7.0. We have to keep 6.0 because of some old LOB application on the internal network. Microsoft is forcing every business to install Chrome or Firefox for general web browsing because you can't run more than one version of IE.

I DO NOT WANT THIS TO PROBLEM EXPAND TO .NET!!!!! I like Microsoft stuff, please don't self destruct .net too. Do not make changes to old libaries, just add new ones.
October 11, 2012 20:29
I'm confused about this whole business of detecting the currently installed version of .Net.

The posts (and urls) above all allude to the fact that it's generally considered bad to try and detect which version is installed (and there apparently isn't a good way to detect what's installed, to boot).

So then what's a guy supposed to do who is writing an installation program for an app that requires .Net 4.5 for example? I'd really like my installation code to be able to detect whether or not the user has the required version of .NET on his system before I install my app. But if detecting the current version of .NET is discouraged, how am I supposed to do that?

October 17, 2012 1:24

If it matters to you then you are not the kind of programmer that Microsoft cares about.

Harsh but true.

They want to you either not care, or use WinRT (until that fails and there is the new API du jour).
November 08, 2012 8:36
It may be a bit ambiguous, but here it's referred to as CLR 4 with an in-place update but still CLR 4.
it's referred to as CLR 4.5 specifically so just want to clear up the confusion.

To your point CLR 5 would be a new CLR but the other chart is a bit misleading then unless we take the fact that any 'x.y' means same version of clr with in-place library changes but still the same base CLR plus maybe some bug fixes and perf improvements.

November 16, 2012 14:00
> An actual bug fix where some totally incorrect behavior was fixed and an existing application was relying on incorrect behavior.

Should NOT be done in an in-place update. Unless it's exceptionally critical.

> An inadvertent breaking change.

WILL happen no matter how much you test, given the scale of the changes .NET 4.5 added. These two reasons together are why .NET 4.5 was clearly supposed to be side-by-side.

Here's an incompatibility I've had to fix yesterday...

Scott, hope you can continue to be the customer's voice and make it blatantly clear that lots of people said it should have been side-by-side, and now that it's out, people still say that.
December 17, 2012 23:49
Scott, can you tell your MS friends that the link to download .NET 4.5 is broken when using this..

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
December 18, 2012 0:31
On both Win7 and Win8, using a .NET 4.5 targeted Windows Forms app with the above config file entry... when the app starts when only .NET 4 is installed it pops open a dialog telling you that .NET 4.5 is not installed and asks if you want to download it. If you choose Yes, it opens this link in a browser..,Version=v4.5

That link then redirects you to..

Which for us is a Page Not Found.

According to Lord Google, the correct url to redirect to is...

It would be great if MS fixed this, as I then wouldnt have to hack around it in my app.
December 18, 2012 0:34
Craig - Thanks. Very sorry they missed this. I'm talking to them now.
December 18, 2012 8:54
Craig - This is fixed now!
December 18, 2012 20:05
Scott could you react to Schaff's post (Saturday, June 02, 2012 4:28:36 AM UTC), please?

This is a complete disaster! What is Microsoft's recommendation for every developer company who has clients running WinXP?
December 19, 2012 11:31
Csabi, I realize it's frustrating and I sympathize. However, remember this is an OS that is 11 years old and 3 OS's ago. MS dropped support for XP in SQL Server 2012. Internet Explorer 9 doesn't run on XP. Adobe has removed XP support in new apps like Lightroom 4.

A new framework in 2012 isn't working in XP that shipped in 2001. However, you CAN still use and target .NET 4 with 2012.
January 04, 2013 13:45
Personally, it was this (relatively recent) post, that put me off 4.5:
January 16, 2013 14:12
Warning 1 The following assembly has dependencies on a version of the .NET Framework that is higher than the target and might not load correctly during runtime causing a failure: AjaxControlToolkit, Version=4.1.60919.0, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e. The dependencies are: System.Web, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a; System.Design, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a; System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35; System.Web.Extensions.Design, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35; System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089; mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089; System.Configuration, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a; System.Windows.Forms, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089; System.Xml, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089; System.Drawing, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a; System.Data, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089; System.Xml.Linq, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089; System.Core, Vers.... You should either ensure that the dependent assembly is correct for the target framework, or ensure that the target framework you are addressing is that of the dependent assembly.
January 18, 2013 2:37
My Web Provider refuses to upgrade to Framework 4.5 – and quite rightly so.

Do you know when Framework 5.0 will become available?

February 01, 2013 14:50
Hi, it seems that David Kean from CLR team replies here:
Since NET4 CLR, there are built in mechanisms for more effective spliting any different implementations according to required assembly versions at native libs too, so NET45 in fact contains "virtually unmodified NET40" behavior (may be still some issues pending, but its designed this way).
So there will be left already published "bugs" the same as in XP supported runtime. Finally, this allows consistent API calls with different behaviors accord to versioning. I personally always trusted that MS must leave even existing bugs in Win32 API and introduce postfix numbers to corercted calls, hope no longer occurs??
February 07, 2013 20:52
In my code, I create a COM server by using Activator.CreateInstance(SomeType). This COM server uses mixed mode SQLite dll compiled against .NET 2.0. I have a config file for this COMServer.exe as follows:

<?xml version="1.0" encoding="utf-8" ?>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
<supportedRuntime version="v2.0.50727"/>

I can positively report the following cases:

1. On Windows 2008 R2 server, this COMServer.exe activates CLR v2.0 without the COMServer.exe.config file at all. It just works.

2. On my Windows 7 machine, this COMServer.exe activates CLR v2.0 for some assemblies and activates CLR v4.0 for some assemblies even the COMServer.exe.config file has this tag: <startup useLegacyV2RuntimeActivationPolicy="true">. COMServer.exe doesn't work here because of mixed match of CLR and mixed mode assembly.

3. On other Windows 7 machine, this COMServer.exe only activates CLR v4.0 with COMServer.exe.config file. It works here.

So what we have here are three different cases and it isn't consistent with what Microsoft is saying. I would like to know why case #2 happens. Why doesn't the config file work as in case #3. Case #1 is a big mystery that Microsoft needs to tell us.
February 21, 2013 7:21
Sad but true story: We upgraded some internal servers (including build server) to 4.5 and we started getting lots of "System.Runtime.CompilerServices.ExtensionAttribute" has been moved issues when deploying to 4.0 servers. Unfortunately this reduced my confidence in just installing 4.5 everywhere to 70%, and management confidence to 0% We've got a lot of websites on shared hosting, and we can't regression test everything, so we're going to follow @schaff's option 1 and ban 4.5 (for now at least)
February 21, 2013 23:02

Can you provide more information on what kind of tools you are using on your build server where you installed 4.5? I'll like to approach the owners and move them over to the features that we in VS 2010 to avoid these situations. We also recently posted a blog post that calls out what they should be doing to avoid this:

February 26, 2013 2:56
Ok for cases where you're using a build server, this post by Marc puts things very clearly:
April 10, 2013 0:34
Another problem here also: installing 4.5 causes a severe focus issue in our application. The application runs WPF with WinForms controls hosted (developed over numerous years), and now two versions of our application are basically crippled if a user installs 4.5.

The decision made to overwrite .net 4.0 with 4.5 seems incredibly near-sighted. I can imagine the mentality was ".net 4.5 will be awesome! we can use an in-place installation to overwrite .net 4.0 and fix bugs!".

Sadly this is simply not practical, as the bugs that existed have already been worked around, and solutions found.

To put it simply:

Keep all versions of the framework available for specific targetting. Any other solution is naive and will inevitably cause issues.
May 29, 2013 2:21
OK so where is the 4.0 version of csc.exe after a 4.5 install?

Gone, Gone, Gone...

Think there is no difference between the output of the two? take a look at the IL (Intermediate Language) difference generated and you will be a true believer 4.0 & 4.5 is not the same and not 100% backward compatible...

Targeting a specific run-time does you no good when csc.exe is different...
August 02, 2013 4:40
Google: "Where is .net 4.5 installed'? Answer: "4.5 is an in place upgrade of 4.0".

This means that there isn't yet another x.y version. Yay! This means that all .net 4.0 apps will get the optimizations and fixes in 4.5. Woohoo! This means that 4.5 apps will fall over on 4.0 mid-way causing additional troubleshooting time only solved by reading this blog and adding detection to my code. Aw! Somehow I have to keep track of features in my code and check if they exist. Boohoo!

Is there a list of such features? Is there a tool that will sniff them out in my code? Isn't this all going to be additional effort for me and become a bit un-maintainable as I remove and add new checks as non in-place versions are released, new in place versions are released on those releases, features are obseleted, etc. Why do I even need to think about this? Isn't this deterministic for .NET? Why doesn't .NET tell me that I am running 4.5 features on 4.0 (or more generally running features that are not supported by the current framework) before it starts? I already have too much framework-assistance bloat code and config settings.

Versioning is hell, so I am not really that upset, but I am not sure that the 4.5 approach was the answer.

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.