61

From the command line (or by any means really), how can I determine which CLR version a .NET assembly requires?

I need to determine if an assembly requires 2.0 or 4.0 CLR version.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222

12 Answers12

61

ildasm.exe will show it if you double-click on "MANIFEST" and look for "Metadata version". By default, it's the version that the image was compiled against.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    To open it maybe press "Win-Start", type 'prompt' and open your Visual-Studio "Developer Command Prompt for VS XXXX". Then you can use 'ildasm' via command-line or type 'ildasm.exe' to open UI and use it like described at this answer. I found ' [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) ' which includes the framework-version. (Maybe maximize the window. Right side of Hex-Value is ASCII-Interpretaion of it) – MichiBack Nov 29 '17 at 15:20
42

One clarification...

The problem with all the mentioned methods is that they will return version 4.0 if assembly was compiled against .NET framework 4.0, 4.5 or 4.5.1.

The way to figure out this version programmatically at runtime is using the System.Runtime.Versioning.TargetFrameworkAttribute for the given assembly, for example

using System;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;

...    

object[] list = Assembly.GetExecutingAssembly().GetCustomAttributes(true);
var attribute = list.OfType<TargetFrameworkAttribute>().First();

Console.WriteLine(attribute.FrameworkName);
Console.WriteLine(attribute.FrameworkDisplayName);

Will return

a.FrameworkName ".NETFramework,Version=v4.0"    string
a.FrameworkDisplayName  ".NET Framework 4"      string

a.FrameworkName ".NETFramework,Version=v4.5"    string
a.FrameworkDisplayName  ".NET Framework 4.5"    string

a.FrameworkName ".NETFramework,Version=v4.5.1"  string
a.FrameworkDisplayName  ".NET Framework 4.5.1"  string
Measurity
  • 1,316
  • 1
  • 12
  • 24
  • 1
    Tried it with a program compiled with command-line `csc`, didn't work (no `TargetFrameworkAttribute`). BTW. your code can be simplified to: `System.Runtime.Versioning.TargetFrameworkAttribute a = list.OfType().First();` – 0xF Jul 08 '14 at 09:08
  • It's only available in .NET 4.0 and upwards, and yeah code can be simplified. – Fernando Gonzalez Sanchez Jul 08 '14 at 15:30
  • Visual Studio sets the .NET version in the csproj, if are compiling a single .cs file, try creating a csproj for it and run for example msbuild myproject.csproj /p:Configuration=Debug /p:Platform="Any CPU" – Fernando Gonzalez Sanchez Jul 09 '14 at 13:19
  • 2
    Of course, this won't work for assemblies compiled for versions < 4, as they won't have the attribute in them. That is, if you want to find out what the *target* (not runtime target) of a compiled assembly you've been given is, and that assembly predates v4, this won't work. – T.J. Crowder Feb 02 '15 at 15:56
34
class Program {
  static void Main(string[] args) { 
      System.Console.WriteLine(
             System.Reflection.Assembly.LoadFrom(args[0]).ImageRuntimeVersion);
  }
}

Compile and run the above application under the latest .NET Framework (as an older CLR may be unable to load assemblies requiring a newer CLR) and run it passing the path to the assembly you want to check as the command line argument.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • This answer is problematic when loading older mixed mode assemblies without the useLegacyV2RuntimeActivationPolicy config flag. – gigaplex Oct 09 '13 at 03:25
  • Thank you. Had an old .NET dll, CCW, I am rewriting/replacing with a 64-bit .NET 4 version and for the life of me couldn't recall for sure if original was still .NET v1.1 or had been touched by a prior migration project and upgraded to v2.x. This did the trick nicely and confirmed our prod version is still v1.1.4322. – Developer63 Feb 20 '15 at 19:49
12

Here's a PowerShell equivalent of the .NET code suggested in another answer. Using PowerShell means that you can skip a few steps like creating and compiling an assembly.

At a PowerShell prompt, run the following:

[System.Reflection.Assembly]::LoadFrom("C:\...\MyAssembly.dll").ImageRuntimeVersion

By default, PowerShell uses the .NET v2 runtime, so you'll get an exception for assemblies targetting v4. Stack Overflow question How can I run PowerShell with the .NET 4 runtime? details methods for changing that, if required.

Community
  • 1
  • 1
Robin Minto
  • 15,027
  • 4
  • 37
  • 40
12

Here is a powershell one liner that will display the Target framework version for assemblies targeting v4 and up.

 Resolve-Path($args) | Select @{N='Assembly'; E={$_ }}, @{N='TargetFramework'; E={(([Reflection.Assembly]::ReflectionOnlyLoadFrom($_).GetCustomAttributesData() | Where-Object { $_.AttributeType -like "System.Runtime.Versioning.TargetFrameworkAttribute" })).NamedArguments.TypedValue}} | Format-Table

use:

C:\test\> show-targetfw.ps1 *.dll

Assembly             TargetFramework
--------             --------
C:\test\a.dll        ".NET Framework 4.6.1"
C:\test\b.dll        ".NET Framework 4.5.2"
Anders Forsgren
  • 10,827
  • 4
  • 40
  • 77
5

From command line

DUMPBIN your dll/exe /CLRHEADER

Tinku
  • 1,592
  • 1
  • 15
  • 27
4

I'd suggest using ReflectionOnlyLoadFrom() insted of LoadFrom()

It has an advantage that it can load x64 and ia64 assemblies when running on x86 machine, while LoadFrom() will fail to do that.

Though it still won't load .Net 4.0 assemblies from a 2.0 powershell.

mistika
  • 2,363
  • 2
  • 21
  • 25
3

As @mistika suggested, it is better to use ReflectionOnlyLoadFrom() rather than LoadFrom(). The downside of this is that calling GetCustomAttributes() on an assembly loaded with ReflectionOnlyLoadFrom() throws an exception. You need to call GetCustomAttributesData() instead:

var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
var customAttributes = assembly.GetCustomAttributesData();
var targetFramework = customAttributes.FirstOrDefault(attr => attr.AttributeType.Equals(typeof(TargetFrameworkAttribute)));

var frameworkName = string.Empty;
var frameworkDisplayName = string.Empty;
if (null != targetFramework)
{
    if(targetFramework.ConstructorArguments.Any())
    {
        // first argument is the name of the framework.
        frameworkName = (string)targetFramework.ConstructorArguments[0].Value;
    }

    // search for a named argument called "FrameworkDisplayName"
    var frameworkDisplayNameArg = targetFramework.NamedArguments.FirstOrDefault(arg => arg.MemberName.Equals("FrameworkDisplayName"));
    if (null != frameworkDisplayNameArg)
    {
        frameworkDisplayName = (string)frameworkDisplayNameArg.TypedValue.Value;
    }
}

Console.WriteLine("Framework Name: " + frameworkName);
Console.WriteLine("Framework Display Name: " + frameworkDisplayName);
Andy
  • 30,088
  • 6
  • 78
  • 89
2

I use ILSpy as a replacement for Reflector. If you open the assembly in ILSpy, you can see, for example:

[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]

xr280xr
  • 12,621
  • 7
  • 81
  • 125
1

A very nice tool is JustDecompile from Telerik. You can open assemblies and the tool is showing whether they are targeting 4.5, 4.5.1 or 4.6

xforfun
  • 592
  • 6
  • 19
0

If you want to include result in a script, I recommend using the text output of ildasm.exe, and then grep "Version String" from the output.

"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe" /text D:\LocalAssemblies\Toolfactory.Core.BaseTypes.dll /noil /headers | find "' Version String"

Note I include a ' so the find command does not recognize "Version String Length"

ferarias
  • 333
  • 2
  • 11
-1

Try this Assembly Information executable to get the assembly version, which tells you CLR version it requires, and as well other information such as Compilation options, Target Processor and References:

enter image description here

yantaq
  • 3,968
  • 2
  • 33
  • 34
  • 2
    This gives the _version of the assembly_, not the .Net version required to run it. – rymdsmurf Feb 23 '17 at 15:00
  • @rymdsmurf, My answer does satisfy OP's need. though it does not give .Net version but it gives assembly version, which tells what .Net version it requires isn' it!. Most of the answer above demonstrates getting assembly version so should you be down voting them all!? – yantaq Mar 06 '17 at 18:40
  • 2
    Your wording, along with the highlighted text in the picture, suggests that your answer explains how to retrieve the assembly version of the original assembly (the one mentioned in the OP's question). But that assembly's version has nothing to do with the version of its framework dependencies. If this is not what you meant, maybe you should formulate the answer in another way, and maybe replace the screenshot. – rymdsmurf Mar 07 '17 at 10:28
  • I appreciate your comment but you left me more confused with yours: "the assembly version of the original assembly"?. it's either assembly version (AKA dll version) or CLR version (runtime version that assembly requires). btw, I re-worded my answer hope it's more clear now. – yantaq Mar 10 '17 at 00:18
  • 2
    "Original" is just me referring to the assembly that caused the OP to ask the question in the first place. As opposed to any referenced (CLR or not) assembly. – rymdsmurf Mar 13 '17 at 13:57
  • 2
    "[...]executable to get the assembly version, which tells you CLR version it requires[...]" But the assembly version _does not_ tell you which CLR version it uses... The assembly version of an arbitrary assembly could be absolutely anything! – rymdsmurf Mar 13 '17 at 14:06
  • In my caes it does tell you CLR version. go do your homework https://assemblyinformation.codeplex.com/SourceControl/latest#AssemblyInformation/AssemblyInformation.cs – yantaq Mar 13 '17 at 19:01
  • https://msdn.microsoft.com/en-us/library/system.reflection.assembly.imageruntimeversion(v=vs.110).aspx – yantaq Mar 13 '17 at 19:01
  • 1
    I really tried to explain this to you, but it seems I'm not getting through. – rymdsmurf Mar 15 '17 at 09:43