11using System ;
2+ using System . Collections . Generic ;
3+ using System . Diagnostics ;
24using System . IO ;
35using System . Linq ;
6+ using System . Reflection ;
7+ using System . Runtime . Versioning ;
48using Microsoft . Win32 ;
59
610namespace BenchmarkDotNet . Helpers
@@ -10,15 +14,62 @@ internal static class FrameworkVersionHelper
1014 // magic numbers come from https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
1115 // should be ordered by release number
1216 private static readonly ( int minReleaseNumber , string version ) [ ] FrameworkVersions =
13- {
17+ [
1418 ( 533320 , "4.8.1" ) , // value taken from Windows 11 arm64 insider build
1519 ( 528040 , "4.8" ) ,
1620 ( 461808 , "4.7.2" ) ,
1721 ( 461308 , "4.7.1" ) ,
1822 ( 460798 , "4.7" ) ,
1923 ( 394802 , "4.6.2" ) ,
2024 ( 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+ }
2273
2374 internal static string GetFrameworkDescription ( )
2475 {
@@ -57,30 +108,28 @@ internal static string MapToReleaseVersion(string servicingVersion)
57108
58109
59110#if NET6_0_OR_GREATER
60- [ System . Runtime . Versioning . SupportedOSPlatform ( "windows" ) ]
111+ [ SupportedOSPlatform ( "windows" ) ]
61112#endif
62113 private static int ? GetReleaseNumberFromWindowsRegistry ( )
63114 {
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" ) ) ;
71120 }
72121
73122#if NET6_0_OR_GREATER
74- [ System . Runtime . Versioning . SupportedOSPlatform ( "windows" ) ]
123+ [ SupportedOSPlatform ( "windows" ) ]
75124#endif
76- internal static string GetLatestNetDeveloperPackVersion ( )
125+ internal static string ? GetLatestNetDeveloperPackVersion ( )
77126 {
78- if ( ! ( GetReleaseNumberFromWindowsRegistry ( ) is int releaseNumber ) )
127+ if ( GetReleaseNumberFromWindowsRegistry ( ) is not int releaseNumber )
79128 return null ;
80129
81130 return FrameworkVersions
82- . FirstOrDefault ( v => releaseNumber >= v . minReleaseNumber && IsDeveloperPackInstalled ( v . version ) )
83- . version ;
131+ . FirstOrDefault ( v => releaseNumber >= v . minReleaseNumber && IsDeveloperPackInstalled ( v . version ) )
132+ . version ;
84133 }
85134
86135 // Reference Assemblies exists when Developer Pack is installed
0 commit comments