1
1
using System ;
2
+ using System . Collections . Generic ;
3
+ using System . Diagnostics ;
2
4
using System . IO ;
3
5
using System . Linq ;
6
+ using System . Reflection ;
7
+ using System . Runtime . Versioning ;
4
8
using Microsoft . Win32 ;
5
9
6
10
namespace BenchmarkDotNet . Helpers
@@ -10,15 +14,63 @@ internal static class FrameworkVersionHelper
10
14
// magic numbers come from https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
11
15
// should be ordered by release number
12
16
private static readonly ( int minReleaseNumber , string version ) [ ] FrameworkVersions =
13
- {
17
+ [
14
18
( 533320 , "4.8.1" ) , // value taken from Windows 11 arm64 insider build
15
19
( 528040 , "4.8" ) ,
16
20
( 461808 , "4.7.2" ) ,
17
21
( 461308 , "4.7.1" ) ,
18
22
( 460798 , "4.7" ) ,
19
23
( 394802 , "4.6.2" ) ,
20
24
( 394254 , "4.6.1" )
21
- } ;
25
+ ] ;
26
+
27
+ internal static string ? GetTargetFrameworkVersion ( )
28
+ {
29
+ // Search assemblies until we find a TargetFrameworkAttribute with a supported Framework version.
30
+ // We don't search all assemblies, only the entry assembly and callers.
31
+ foreach ( var assembly in EnumerateAssemblies ( ) )
32
+ {
33
+ foreach ( var attribute in assembly . GetCustomAttributes < TargetFrameworkAttribute > ( ) )
34
+ {
35
+ switch ( attribute . FrameworkName )
36
+ {
37
+ case ".NETFramework,Version=v4.6.1" : return "4.6.1" ;
38
+ case ".NETFramework,Version=v4.6.2" : return "4.6.2" ;
39
+ case ".NETFramework,Version=v4.7" : return "4.7" ;
40
+ case ".NETFramework,Version=v4.7.1" : return "4.7.1" ;
41
+ case ".NETFramework,Version=v4.7.2" : return "4.7.2" ;
42
+ case ".NETFramework,Version=v4.8" : return "4.8" ;
43
+ case ".NETFramework,Version=v4.8.1" : return "4.8.1" ;
44
+ }
45
+ }
46
+ }
47
+
48
+ return null ;
49
+
50
+ static IEnumerable < Assembly > EnumerateAssemblies ( )
51
+ {
52
+ var entryAssembly = Assembly . GetEntryAssembly ( ) ;
53
+ // Assembly.GetEntryAssembly() returns null in unit test frameworks.
54
+ if ( entryAssembly != null )
55
+ {
56
+ yield return entryAssembly ;
57
+ }
58
+ // Search calling assemblies.
59
+ var stacktrace = new StackTrace ( false ) ;
60
+ var searchedAssemblies = new HashSet < Assembly > ( )
61
+ {
62
+ stacktrace . GetFrame ( 0 ) . GetMethod ( ) . ReflectedType . Assembly
63
+ } ;
64
+ for ( int i = 1 ; i < stacktrace . FrameCount ; i ++ )
65
+ {
66
+ var assembly = stacktrace . GetFrame ( i ) . GetMethod ( ) . ReflectedType . Assembly ;
67
+ if ( searchedAssemblies . Add ( assembly ) )
68
+ {
69
+ yield return assembly ;
70
+ }
71
+ }
72
+ }
73
+ }
22
74
23
75
internal static string GetFrameworkDescription ( )
24
76
{
@@ -57,30 +109,28 @@ internal static string MapToReleaseVersion(string servicingVersion)
57
109
58
110
59
111
#if NET6_0_OR_GREATER
60
- [ System . Runtime . Versioning . SupportedOSPlatform ( "windows" ) ]
112
+ [ SupportedOSPlatform ( "windows" ) ]
61
113
#endif
62
114
private static int ? GetReleaseNumberFromWindowsRegistry ( )
63
115
{
64
- using ( var baseKey = RegistryKey . OpenBaseKey ( RegistryHive . LocalMachine , RegistryView . Registry32 ) )
65
- using ( var ndpKey = baseKey . OpenSubKey ( @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" ) )
66
- {
67
- if ( ndpKey == null )
68
- return null ;
69
- return Convert . ToInt32 ( ndpKey . GetValue ( "Release" ) ) ;
70
- }
116
+ using var baseKey = RegistryKey . OpenBaseKey ( RegistryHive . LocalMachine , RegistryView . Registry32 ) ;
117
+ using var ndpKey = baseKey . OpenSubKey ( @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" ) ;
118
+ if ( ndpKey == null )
119
+ return null ;
120
+ return Convert . ToInt32 ( ndpKey . GetValue ( "Release" ) ) ;
71
121
}
72
122
73
123
#if NET6_0_OR_GREATER
74
- [ System . Runtime . Versioning . SupportedOSPlatform ( "windows" ) ]
124
+ [ SupportedOSPlatform ( "windows" ) ]
75
125
#endif
76
- internal static string GetLatestNetDeveloperPackVersion ( )
126
+ internal static string ? GetLatestNetDeveloperPackVersion ( )
77
127
{
78
- if ( ! ( GetReleaseNumberFromWindowsRegistry ( ) is int releaseNumber ) )
128
+ if ( GetReleaseNumberFromWindowsRegistry ( ) is not int releaseNumber )
79
129
return null ;
80
130
81
131
return FrameworkVersions
82
- . FirstOrDefault ( v => releaseNumber >= v . minReleaseNumber && IsDeveloperPackInstalled ( v . version ) )
83
- . version ;
132
+ . FirstOrDefault ( v => releaseNumber >= v . minReleaseNumber && IsDeveloperPackInstalled ( v . version ) )
133
+ . version ;
84
134
}
85
135
86
136
// Reference Assemblies exists when Developer Pack is installed
0 commit comments