Assembly.LoadFrom BadImageFormatException - different behavior in .NET 4.0 and 4.5 (possibly undocumented) - .net-4.0

According to MSDN documentation,
public static Assembly LoadFrom(string assemblyFile)
throws BadImageFormatException if
assemblyFile is not a valid assembly.
-or-
Version 2.0 or later of the common language runtime is currently loaded
and assemblyFile was compiled with a later version.
Actually, there is one extra case - loading assembly that is built for x86 from assembly that runs in x64 mode. Maybe it is included in "not a valid assembly" statement, I don't know. But this is reasonable cause of exception.
Ok, but in .NET 4.5 it doesn't! I have a .NET 4.5 WPF app, that loads different appliations for some reason. It is building for Any CPU and I'm starting it on x64 Win 7. I've been testing it on one executable, that is built for .NET 4.0 x86, and it worked fine. But when I switched my app to .NET 4.0 it began to crash on Assembly.Load method!
So, my question is, am I missing something? If not, then how did they do that - loading x86 assembly from x64 process in .NET 4.5? I'm lacking some understanding at this point.
Update
Thanks to Hans Passant, I've figured out my mistake. Actually the behavior of Assembly.Load is no different. It turned out, I didn't notice Prefer 32-bit option in project settings (or Prefer32Bit tag in .csproj file). That's why my process in .NET 4.5 ran in a 32-bit mode. This setting was true when I created WPF .NET 4.5 project. Then, when I swithced to .NET 4.0 it became inactive because there was no such an option in .NET 4.0. And when I switched back to .NET 4.5 it became false, which is so, I guess, for compatibility purpose.

Let's clear one assumption off the table quickly, there is no possible way to have different behavior on a machine that has .NET 4.5 installed. Targeting 4.0 makes no difference at runtime. The only thing that does is select a different set of reference assemblies, they prevent you from accidentally using a class that's available on .NET 4.5 but not on .NET 4.0.
There is no way to have both 4.0 and 4.5 installed on the same machine. .NET 4.5 is not a side-by-side version of the .NET framework, like 3.5 and 4.0 are side-by-side. Installing 4.5 replaces an installed 4.0 version. The CLR, the jitter, all the runtime assemblies plus the C# compiler.
It is best here to focus on the Platform target setting of your EXE project, that's the one that selects the bitness of the process. The kind of mistakes you can make is forgetting that the setting can be different for the Debug vs the Release build. And assuming that the "Active solution platform" combobox in Build + Configuration Manager has any effect. It doesn't, only the Project + Properties, Build tab, Platform target setting matters. This is a very awkward trap that many programmers have fallen into.

Related

Portable F# library references .NET 4.5 (but not 4.0)

I'm trying to create portable F# library but it needs to target .NET 4.0 (company policy is that all portable libraries need to be compatible with Windows XP).
When I create (Visual Studio 2013) new project there is an option "Portable Library (Legacy)" with description saying "A project for creating an F# library (.dll) that can run on .NET Framework 4.0 and higher, Windows Store and Silverlight 5".
The problem is, when the project is actually created. When I go to project's properties "Target Framework" is set to ".NET Portable Subset (.NET Framework 4.5, Silverlight 5, Windows 8)".
I tried changing F# runtime version from 3.1 to 3.0 but it does not change anything. "3.0" and "3.1" are the only options. What happened to "2.0"?
Am I missing something?
EDIT: It seems like Grzegorz is right. I've created this F# PCL which is saying ".NET 4.5" and referenced it from .NET 4.0 C# application. No problems were reported.
Then, to be sure, I also referenced it from 3.5 application and... no problems were reported during compilation either, but it was crashing on runtime. So to be sure, I ran the "potentially 4.0" application on XP and it worked, which may be interpreted as: "Yes, F# PCL does not depend on 4.5 even it it says so".
Make it an answer so I can tick it.
The template file for "Portable Library (Legacy)" has TargetFrameworkVersion hardcoded as v4.0. If You'll create a project with this template it'll in fact target 4.0 version.
Probably, there's a bug in UI that keeps displaying target framework as 4.5 while in reality it uses previous one.
To be strict, the issue is related to legacy Portable Library. The non-legacy version seems to work correctly in forcing framework to be in 4.5 version.
update:
I submitted an issue about this to Visual F# Tools team:
https://visualfsharp.codeplex.com/workitem/95

Require .NET 4.0 for .NET 4.5 app

This is a two part question. I need both parts addressed for a complete answer.
Part I
I have a .NET 4.5 desktop app and I'm wondering if I can deploy it to Windows XP if, within "Requirements" in the app's Installshield project, I tick the ".NET 4.0 Full Package is Installed" checkbox instead of the ".NET 4.5 Full Package is Installed" one.
I read here that:
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.
So I know what the ability of my app to run on Windows XP with .NET 4.0 depends on. Let's assume for this question that my app won't crash as described in the above quote.
Part II
I also need to know what effect choosing ".NET 4.0 Full Package is Installed" instead of ".NET 4.5 Full Package is Installed" will have when installing the app onto a machine with .NET 4.5, but not .NET 4.0, installed. Will the Installshield installer see the installed .NET 4.5 package as .NET 4.0 and thus not complain? Or will it be picky and block the app's installation since specifically .NET 4.0 is not installed?
First thing you need to do is change the Target Framework version of your projects from 4.5 to 4.0 and rebuild. If you used any 4.5 specific feature then you'll now find out. You'll need to fix errors.
Part 2 is a non-issue, .NET 4.5 is a replacement for .NET 4.0. The installer is not going to uninstall 4.5 first so it can install 4.0, that would break all existing .NET apps on that machine.

Changing framework 4.0 to 2.0 without affecting any reference

I have developed a Windows application in the 4.0 framework. After deploying my application I have tried to install it in a Windows XP SP2 system, but when I try it I get some kind of requirement error. So I decided to change my application from 4.0 to the 2.0 framework so that it can be installed in any windows OS. Before that I tried with 3.5 and 3.0 but the framework's setup size exceeded 200mb, so I chose 2.0 because it already comes along with windows xp or later. The problem I am having is while changing my framework from 4.0 to 2.0 i'm getting reference problems with system.core and system.linq so now I cant build my project. What needs to be done to fix these reference errors?
The problem is that System.Linq, for example, didn't exist in .NET 2. If you are using anything that required System.Linq methods (such as LINQ or any extension methods), you'll have to rewrite that portion of your code to use .NET 2 only options.
Personally, I would just target .NET 3.5sp1 or .NET 4, and include the web installer, as this is a small addition to your deployment (the 4.0 web installer is under 1mb - many installers include a way to just package this instead of the full framework). Most systems already have .NET 3.5sp1 (and many have 4.0), so the effort to include this in your deployment is typically far smaller than trying to rework your application to avoid it.

Building 4.5 code without the 4.5 runtime installed on the machine?

We have a large & complex system running under .Net 4.0. We want to start introducing code written for .Net 4.5, but can't (yet) assume that .Net 4.5 is installed on all the developer machines, build machines and test labs. So I'm looking for a way to compile certain projects in MSBuild using assemblies which are available on disk, on machines which have only .Net 4.0 installed.
Per the documentation it seems possible. The 4.5 reference assemblies are available in the msbuild environment, and I've been experimenting with the TargetFrameworkVersion, FrameworkPathOverride and TargetFrameworkMoniker attributes, but so far without success.
Any hints, suggestions or working samples would be most helpful.
To build a .NET Framework 4.5 application, you must also have the .NET Framework 4.5 reference assemblies.
Installation
The .NET Framework 4.5 replaces the common language runtime (CLR), targets, tasks, and tools of the .NET Framework 4 without renaming them. Essentially, it creates a modified and improved .NET Framework 4.

Using a .NET 4.0 DLL in Unity3d via COM/SxS?

In an attempt to oversimplify my issue, I'll try to keep it short:
I'm using the pro version of Unity, and I have 2 DLLs:
A .NET 3.5 assembly (acting as a COM client)
A .NET 4.0 assembly (with an interface exposed via COM)
The 3.5 uses COM to work with the 4.0. Using the 3.5 assembly in a Windows app works fine, it loads the 4.0 dll using SxS via Type.GetTypeFromCLSID() or Type.GetTypeFromProgID() (which I've confirmed with SxStrace), and can use it's functionality just fine. (The windows app mentions it's dependency on the 4.0 DLL via a manifest, I'm not registering the COM DLL.)
I'm trying to use the .NET 4.0 DLL in Unity. Obviously I can't use it directly, since the current flavor of Mono that Unity uses only supports up to 3.5, thus I created the 3.5 assembly to be my middleman. I'm able to use the 3.5 assembly fine in unity, but either of the Type methods I mentioned before throw NotImplementedException(s), as apparently they aren't supported by Unity (or rather, Mono), so I'm at a loss.
Any ideas?
Although this question was made 1 year ago..sadly the middleman tactic still wont work, it is not possible to use .NET 4.0 dlls within Unity3D since Mono is just not supporting the dependencies.
You could try to remove any 4.0 dependencies from the dll and compile it as 3.5, if that is possible for you.