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