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,62 @@ 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 currentAssembly = stacktrace . GetFrame ( 0 ) . GetMethod ( ) . ReflectedType . Assembly ;
61
+ for ( int i = 1 ; i < stacktrace . FrameCount ; i ++ )
62
+ {
63
+ StackFrame frame = stacktrace . GetFrame ( i ) ;
64
+ var assembly = frame . GetMethod ( ) . ReflectedType . Assembly ;
65
+ if ( assembly != currentAssembly )
66
+ {
67
+ currentAssembly = assembly ;
68
+ yield return assembly ;
69
+ }
70
+ }
71
+ }
72
+ }
22
73
23
74
internal static string GetFrameworkDescription ( )
24
75
{
@@ -57,30 +108,28 @@ internal static string MapToReleaseVersion(string servicingVersion)
57
108
58
109
59
110
#if NET6_0_OR_GREATER
60
- [ System . Runtime . Versioning . SupportedOSPlatform ( "windows" ) ]
111
+ [ SupportedOSPlatform ( "windows" ) ]
61
112
#endif
62
113
private static int ? GetReleaseNumberFromWindowsRegistry ( )
63
114
{
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
- }
115
+ using var baseKey = RegistryKey . OpenBaseKey ( RegistryHive . LocalMachine , RegistryView . Registry32 ) ;
116
+ using var ndpKey = baseKey . OpenSubKey ( @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" ) ;
117
+ if ( ndpKey == null )
118
+ return null ;
119
+ return Convert . ToInt32 ( ndpKey . GetValue ( "Release" ) ) ;
71
120
}
72
121
73
122
#if NET6_0_OR_GREATER
74
- [ System . Runtime . Versioning . SupportedOSPlatform ( "windows" ) ]
123
+ [ SupportedOSPlatform ( "windows" ) ]
75
124
#endif
76
- internal static string GetLatestNetDeveloperPackVersion ( )
125
+ internal static string ? GetLatestNetDeveloperPackVersion ( )
77
126
{
78
- if ( ! ( GetReleaseNumberFromWindowsRegistry ( ) is int releaseNumber ) )
127
+ if ( GetReleaseNumberFromWindowsRegistry ( ) is not int releaseNumber )
79
128
return null ;
80
129
81
130
return FrameworkVersions
82
- . FirstOrDefault ( v => releaseNumber >= v . minReleaseNumber && IsDeveloperPackInstalled ( v . version ) )
83
- . version ;
131
+ . FirstOrDefault ( v => releaseNumber >= v . minReleaseNumber && IsDeveloperPackInstalled ( v . version ) )
132
+ . version ;
84
133
}
85
134
86
135
// Reference Assemblies exists when Developer Pack is installed
0 commit comments