问题
Is there any way that I can access the values that were used for TargetFrameworkVersion and/or TargetFrameworkProfile when a .Net assembly was compiled?
The values I'm talking about are the ones contained the project file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OtherStuff>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<OtherStuff>
</PropertyGroup>
<OtherStuff>
</OtherStuff>
</Project>
Basically I'd like to find out what the Target Version of the Framework was when the assembly was compiled and if possible the Target Framework Profile as well.
And I'm not talking about the currently loaded version of the CLR, Environment.Version isn't what I'm after.
Ideally the solution would use System.Reflection but if I have to resort to other methods I will.
回答1:
If you would be satisfied with the version of the CLR that compiled the assembly, you can use the Assembly.ImageRuntimeVersion property. According to MSDN, that property:
representing the version of the common language runtime (CLR) saved in the file containing the manifest.
and
By default, ImageRuntimeVersion is set to the version of the CLR used to build the assembly. However, it might have been set to another value at compile time.
Of course, that doesn't give you the specific version of the .NET Framework (for example: .NET Frameworks 2, 3.0 and 3.5 are all on the 2.0 CLR).
If the CLR version isn't sufficient, you could to try to 'estimate' (guess intelligently) what version it must be based on the assemblies it references. For .NET 1 and 4, the CLR version should be enough. However, if the CLR version was 2.0, you wouldn't know if that meant 2.0, 3.0, or 3.5 so you could try some more logic. For example, if you saw that the Assembly referenced System.Core
(using Assembly.GetReferencedAssemblies()) then you would know that the version is 3.5 since System.Core
was new in 3.5. That's not exactly rock-solid since the assembly in question might not use any types from the Assembly so you wouldn't be able to catch that. To try to catch more cases, you could loop through all the referenced assemblies and check their version numbers - maybe filtering to just assemblies that start with System to avoid false positives with other libraries. If you see any System.* assemblies referenced that have a version of 3.5.x.x, then you can also be pretty sure it was built for 3.5.
As you've noticed, I don't believe the TargetFrameworkProfile
escapes past Visual Studio. However, if there happens to be an app.config file for the application, Visual Studio may have put the target framework in there. For example, if you set project to use the 4.0 Client Profile, Visual Studio creates an app.config like this:
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
</startup>
</configuration>
回答2:
If the assembly was compiled with the TargetFrameworkAttribute (assembly scoped) you can easily and uniformly determine the framework profile target.
Try this example and reference your own custom assemblies with different targets.
class Program
{
static void Main(string[] args)
{
// Lets examine all assemblies loaded into the current application domain.
var assems = AppDomain.CurrentDomain.GetAssemblies();
// The target framework attribute used when the assemby was compiled.
var filteredType = typeof(TargetFrameworkAttribute);
// Get all assemblies that have the TargetFrameworkAttribute applied.
var assemblyMatches = assems.Select(x => new { Assembly = x, TargetAttribute = (TargetFrameworkAttribute)x.GetCustomAttribute(filteredType) })
.Where(x => x.TargetAttribute != null);
// Report assemblies framework target
foreach (var assem in assemblyMatches)
{
var framework = new System.Runtime.Versioning.FrameworkName(assem.TargetAttribute.FrameworkName);
Console.WriteLine("Assembly: '{0}' targets .NET version: '{1}'.",
assem.Assembly.FullName,
framework.Version);
}
Console.ReadLine();
}
}
回答3:
Try also this example to retrieve both target and current versions of .NET framework at runtime (works for .NET V4.X) :
Dim ca As Object() = System.Reflection.Assembly.GetEntryAssembly().GetCustomAttributes(False)
For Each c In ca.Where(Function(x) x.TypeId.Name = "TargetFrameworkAttribute")
Console.WriteLine("Target .NET framework for " & Application.ProductName & " : " & c.FrameworkDisplayName)
Next
Console.WriteLine("Current .NET framework for " & Application.ProductName & " : " & System.Diagnostics.FileVersionInfo.GetVersionInfo(GetType(Integer).Assembly.Location).ProductVersion)
回答4:
njappboy's solution works great. I needed VB.Net version, so here's the conversion.
Dim assems = AppDomain.CurrentDomain.GetAssemblies()
Dim filteredType = GetType(Runtime.Versioning.TargetFrameworkAttribute)
Dim assemblyMatches = assems.[Select](Function(x) New With {Key .Assembly = x,
Key .TargetAttribute = CType(x.GetCustomAttribute(filteredType),
Runtime.Versioning.TargetFrameworkAttribute)}).Where(
Function(x) x.TargetAttribute IsNot Nothing)
For Each assem In assemblyMatches
Dim framework = New System.Runtime.Versioning.FrameworkName(
assem.TargetAttribute.FrameworkName)
Console.WriteLine("Assembly: '{0}' targets .NET version: '{1}'.",
assem.Assembly.FullName, framework.Version)
Next
来源:https://stackoverflow.com/questions/6854664/retrieve-target-framework-version-and-target-framework-profile-from-a-net-assem