问题
Just a little setup. We have the .Net framework 3.5, 4.0, 4.5, and 4.6.1 installed.
If we build a .Net application or assembly using .Net framework 3.5 and then we set the app.config to run using a single supported runtime of 4.6.1:
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup>
Which version of the framework is actually being utilized?
This question came from from reading this post: How do I force an application compiled to target .NET Framework 4 to run under .NET framework 4.6.1?. @Hans Passant states that the TargetFrameworkAttribute will dictate how the framework will behave and he talks about there being switches that cause specific code to run, etc.. However, I haven't found anything that explains which version of the core .Net framework will be running in this scenario.
Will any calls to the .Net framework use the .Net 3.5 code base, the .Net 4.0 code base (because of the 4.0 clr version), or will the latest and greatest .Net 4.6.1 code base be run because that is the latest version installed using the clr 4.0?
Edit: To show the manifest that does not specifically state the runtime version.
// Metadata version: v2.0.50727
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly ConsoleApplicationVersionTest
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 1D 43 6F 6E 73 6F 6C 65 41 70 70 6C 69 63 // ...ConsoleApplic
61 74 69 6F 6E 56 65 72 73 69 6F 6E 54 65 73 74 // ationVersionTest
00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 1D 43 6F 6E 73 6F 6C 65 41 70 70 6C 69 63 // ...ConsoleApplic
61 74 69 6F 6E 56 65 72 73 69 6F 6E 54 65 73 74 // ationVersionTest
00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20 // ...Copyright ..
20 32 30 31 36 00 00 ) // 2016..
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 34 36 36 31 33 34 32 33 2D 38 39 34 30 // ..$46613423-8940
2D 34 39 36 65 2D 61 31 37 32 2D 37 36 36 31 31 // -496e-a172-76611
64 30 66 31 32 32 38 00 00 ) // d0f1228..
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module ConsoleApplicationVersionTest.exe
// MVID: {11493526-C9AC-45F0-9784-D7712809998C}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x00000000010B0000
回答1:
We have the .Net framework 3.5, 4.0, 4.5, and 4.6.1 installed
That is not accurate, such a configuration is not possible. The rule is that you can have only one version of .NET 2.0 through 3.5 installed, it targets the v2.0.50727 runtime. And one version of .NET 4.0 through 4.6.2 installed, it targets the v4.0.30319 runtime.
So your machine might have had 4.0 installed. When you installed 4.5 it overwrote the 4.0 install. No trace of it is remaining. 4.5 is quite capable of running programs that target 4.0, Microsoft spent an enormous amount of effort to ensure that 4.5 is backwards compatible with 4.0. And likewise, when you installed 4.6.1 it overwrote 4.5
// Metadata version: v2.0.50727
The ildasm.exe dump you posted clearly shows that the assembly targets the 2.0.50727 runtime. So easy peasy, it is going to run on the 3.5 version. It will run just as well on a 2.0 install, it doesn't use any assemblies that were added in 3.0 and 3.5. Maybe that's your cue, Microsoft increments the framework version when it adds new assemblies. Only when it creates a new runtime version can you have another side-by-side install. That's not very likely to happen anytime soon, not counting .NETCore which took a completely different approach.
回答2:
You can use ILDasm.exe and parse the output. The below is powershell function I uses all the time, and can be very easily migrated to .net VB/C#. Modify the ILDasm.exe path as per your environment.
function Get-NetFrameworkVersion
{
param([string]$path)
if($path)
{
$ildasmpath = 'C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe'
$ildasmswitches = '/header /noil /text'
$netframeworkverspattern="//\s+'v(?<version>[0-9.]+)'\s+Version String"
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $ildasmpath
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.CreateNoWindow = $true
$pinfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
$pinfo.Arguments = '"' + $path + '" ' + $ildasmswitches
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$dumpcontent = $p.StandardOutput.ReadToEnd()
$p.WaitForExit()
if([string]$dumpcontent -match $netframeworkverspattern)
{
$Matches.version
}
}
}
来源:https://stackoverflow.com/questions/38752826/which-version-of-the-net-framework-is-my-assembly-actually-running