Does Windows cache the .NET version used by an assembly? - c#

I made the mistake of trying to deploy a program built with .NET 4.7.1 on a machine that didn't have that version of the .NET framework installed. It popped the following error message:
Since installing a new .NET framework requires a reboot, I don't want to go that route yet. So I tried downgrading the target framework to 4.6.1... but I still get the same error!
I verified that the assembly was compiled targeting the 4.6.1 framework:
As a test, I renamed the assembly VueLinks2.exe and it started just fine.
The only thing I can think of is that Windows "remembers" what framework is associated with an assembly. Is that correct? Is it possible to undo that and downgrade an app to a previous version without renaming the file?

There's no cache. Deciding what framework to use is a combination of the <requiredRuntime> (legacy) and <supportedRuntime> elements in the [exe].app.config and the assembly's framework version if those are not supplied. Renaming the executable will cause the [exe].app.config to no longer be matched.

Related

'Could not load file or assembly 'netstandard, Version=2.0.0.0, ...'. Reference assemblies should not be loaded for execution

Goal:
From a .NET 4.7 console app, using reflection with Assembly.GetType(), I am trying extract the Type of a netstandard 2.0 class from Assembly X. Then I want to create an instance of this Type with Activator.CreateInstance().
What I am trying to do:
However, this assembly X has a dependency to netstandard 2.0. To be able to get the Type, netstandard dependency has to be loaded into the AppDomain. That's why when the AppDomain is requesting the netstandard assembly through the AssemblyResolve event, I simply load the dll like this :
var netStandardDllPath = #"C:\Users\xxx\.nuget\packages\NETStandard.Library.2.0.0-preview1-25301-01\build\netstandard2.0\ref\netstandard.dll";
return Assembly.LoadFrom(netStandardDllPath);
Which throws:
System.BadImageFormatException: 'Could not load file or assembly
'file:///C:\Users\vincent.lerouvillois.nuget\packages\NETStandard.Library.2.0.0-preview1-25301-01\build\netstandard2.0\ref\netstandard.dll'
or one of its dependencies. Reference assemblies should not be loaded
for execution. They can only be loaded in the Reflection-only loader
context. (Exception from HRESULT: 0x80131058)'
Inner Exception: BadImageFormatException: Cannot load a reference
assembly for execution.
What I know:
I know that they want us to load the DLL with Assembly.ReflectionOnlyLoadFrom. But doing that will prevent me from instanciate the type with Activator.CreateInstance(). See Microsoft official post
Also, I tried referencing the Nuget packages NETStandard.Library 2.0.0-preview1-25301-01 and NETStandard.Library.NETFramework 2.0.0-preview1-25305-02 in my console app so it would have the netstandard 2.0 libraries referenced, but it didn't change anything.
Question:
Does anyone would know if there is a proper way to load that dll without error, or maybe if this is a bug, or else? Or why this kind of dll is not able to load for execution?
The netstandard.dll you are trying to load is a reference assembly that which cannot be loaded for runtime on .NET Framework as pointed out by others. However if you need to resolve that dependency you will need to runtime version that maps to the framework you are trying to run on.
For .NET Standard support we are including them as part of the msbuild extensions that ship with VS so you will want to get the version of netstandard.dll from there. Depending on which version of VS2017 you have installed it should be somewhere like C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\netstandard.dll or from the .NET Core 2.0 SDK you can find it C:\Program Files\dotnet\sdk\2.0.0\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\netstandard.dll
Try using one of those versions in your scenario.
Wow. I just spent several hours tracking the cause of this "could not load ... netstandard" error down.
For me, the problem was that my .NET Framework project (which references both .NET Framework and .NET Standard libraries) was built with .NET Framework 4.7.2 and the system where I was deploying and running it did not have 4.7.2 installed.
Deploying a very small Console project with the same basic structure and references and executing that in a Command window finally revealed the correct error, in a pop-up, that .NET Framework 4.7.2 was missing.
If you're struggling with this particular error, make sure you have the necessary .NET Framework installed.
Set Copy Local to true in netstandard.dll properties.
Open Solution Explorer and right click on netstandard.dll.
Set Copy Local to true.
You can't load a reference assembly.
.NET Standard is a collection of APIs that must be provided by .NET Standard compatible implementations.
A reference assembly only contains contracts. This means that it contains no implementation. The assembly you are trying to load contains the .NET Standard 2.0 contracts.
A contract looks like this: https://github.com/dotnet/standard/blob/master/netstandard/ref/mscorlib.cs
EDIT: .NET Framework 4.7 implements .NET Standard 2.0, so you shouldn't need to load any assembly to use Activator.CreateInstance() to instantiate a .NET Standard type.
NETStandard 2.0.0-preview1 in not compatibility with net461 and net47.
but for realese .NET Core SDK 2.0 assemblies (as well as 2.0.0-preview2)
var netStandardDllPath = #"c:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.0.0\ref\netcoreapp2.0\netstandard.dll";
Console.WriteLine(Assembly.LoadFrom(netStandardDllPath).FullName);
all is ok.
But if you steel need to load preview1 libraries, maybe you should to use netstandard2.0 instead net471.
For me solved doing the following:
1 - Installed latest .Net Framework on server.
2 - Updated windows server and my local machine.
3 - Went to Manage Nuget Package and updated all references on the update tab.
Perhaps only doing step 3 can solve in your case
In case if IBM Message Queue references are used in the project solution, this exception indicates that the DLL used for refering MQ classes are incompatible with the host(server) .NET version installed.
In this scenario, either we need to update server with latest update and make sure .NET latest version is available or use lower version of IBM Message queue DLL as reference.
Old version DLL - amqmdnet.dll (no new features will be introduced by IBM as not in support)
Latest version DLL - amqmdnetstd.dll (to run IBM MQ classes for .NET Standard, you must install Microsoft .NET Core)
Install NetStandard.Library 2.0.0.0 from NuGet , It works for me. when I downgrade .net framework 4.6.1 to 4.6.0
If you are having this issue for a project that used to work, try deleting the bin and obj folders since caching can cause this, too.

Identifying the version of Entity Framework

One of our development machines is giving an error saying that DbContext does not implement IDisposable. According to a similar SO post, this is because we are not referencing EF 5. The problem assembly has a *.edmx file built with older EF 4 constructs (ObjectContext). This same assembly also has a newly added *.edmx file with the newer constructs (DbContext).
A different project on a different machine also uses DbContext and works fine. Said project shows the following information for EntityFramework.dll:
version: 4.4.0.0
Runtime Version: v4.0.30319
I checked the bad build machine and it also has this same version of EntityFramework.dll.
Microsoft has had confusing conflicts between development and marketing version naming conventions. So does EF 5 mean the dll version should say 5.0?
In other words, am I running v4.0 on the good build machine? If so why is the build successful?
The Entity Framework v5.0 dll is dependent on the .NET CLR you are targeting. If your project is set to use the .NET 4.0 framework, the runtime version of the EntityFramework.dll will be 4.4.0.0.
If you are using Entity Framework with a CLR target of .NET 4.5, the version of the EntityFramework.dll will be 5.0.
When you add EntityFramework via nuget, it will look at your project's CLR target runtime and add the appropriate EntityFramework.dll reference. If you later change your target, you should uninstall and reinstall the EntityFramework reference via nuget to make sure that the correct version of the runtime is referenced by your project.
Reference post by Julie Lerman about the topic.

Framework Upgrade to 3.5

I have a project which references another project's dll. They both were in .net framework 2.0.
So upgraded both to 3.5, but when I go to reference for second project(the one referencing the first project) it still says on properties runtime version 2.0, even though I deleted the reference and readded.
How would I determine if the referenced dll is the upgraded one, before deploying to server where it has version 2.0?
I don't want to delete all files in server and deploy, after upgrading do I need to check the config files are referencing same dlls and deploy published files or it needs replacing all together?
.Net 3.5 and .Net 2 both run on version 2 of the CLR, so the runtime version of the 'old' and 'upgraded' assemblies will not change.
As for finding out whether it is 'upgraded', I would recommend using ILDASM to see which version of mscorlib is referenced.
However, the answers to this SO question provide a few alternatives.
You can easily check which version the assembly is build against by opening it up in Reflector (or another decompiler).
The CLR for .NET 3.0 and .NET 3.5 is the same CLR from .NET 2.0.
Hence the best way to check, if your assemblies are upgraded or not, is to use Assembly version. Do maintain assembly version and build version in AssemblyInfo.cs while building the assembly.
Having a strong named assembly is the best way to check.

Problems with targeting my VS2010 to .NET4 Framework

I keep getting the following messages about frameworks in VS2010. Also I can no longer add .net 4 as a target framework. I have tried installing / repairing the .net 4 framework. It keeps telling me all is okay but then I still get the message and cannot target the .net 4 or add it from the drop down list in the project properties. I'm at a loss for what to do. Any advice would be much appreciated.
Warning 8 The reference assemblies for framework ".NETFramework,Version=v4.0" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend.
Have you tried downloading and installing this?:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8279
It has worked for other people.
As far as I am aware this is different than the .NET framework, which is just for running the apps.
C:\Program Files[ (x86)]\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0
This is the folder VS looks for reference assemblies. Does it contain the correct things on your machine? If not, you need to repair VS.
This folder is not part of .NET 4 installation, so that's why repair .NET 4 does not help you much.

Why does referncing earlier .net versions work on my local machine but not on another?

I have winforms application. When I look at the references they are all .net 4 (same as the application) apart from one which says v2.0. I can run the app locally and use functionality from the .net components but as soon as I take the app to another machine it wont fire up. Apparently this hapens when references cant be found.
Im very confused as to why this would work locally. I have checked the GAC and only .net 2.0 versions exist for the referenced dlls.?..
What are the rules around rererencing dlls from older versions on .net?
It is perfectly fine to have the two versions of the framework running on the same machine. Are both .NET 2 and .NET 4 installed on the second machine you are testing on? I suspect that they are not.
Yes you can reference .Net 2.0 dlls from .Net 4.0 project.
You might be referencing only .Net 2.0 dlls but your target framework might be .Net 4.0, which might not be available on your other machine.
To correct this:
Open your project properties.
Set Target framework to .Net Framework 2.0 or 4.0.
If you set it to 4.0, you must have 4.0 installed on the machine you want it to run on.
The quickest way to see which versions are installed on a machine:
open VS command prompt and type clrver. (Ofcourse you'll need .Net SDK)
To see which framework your app uses type clrver
you can get for your application from task manager (in process tab, click View->select columns->check PID)
Starting .NET 4.0, your app can target multiple frameworks in different AppDomains in the same process.
Remember that the framework that your application is determined automatically, but you can override this default behaviours. One way to do this is what I described above.
Note that the GAC location has changed between .Net 2.0 and .Net 4.0. You most likely have both versions installed on your machine and you have looked at the 2.0 GAC.
The second machine most likely does not have 2.0 installed, hence it fails running.

Categories