1717
1818namespace Microsoft . Build . Locator
1919{
20- internal static class DotNetSdkLocationHelper
20+ internal static partial class DotNetSdkLocationHelper
2121 {
22- private static readonly Regex VersionRegex = new Regex ( @"^(\d+)\.(\d+)\.(\d+)" , RegexOptions . Multiline ) ;
23- private static readonly bool IsWindows = RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ;
24- private static readonly string ExeName = IsWindows ? "dotnet.exe" : "dotnet" ;
25- private static readonly Lazy < IList < string > > s_dotnetPathCandidates = new ( ( ) => ResolveDotnetPathCandidates ( ) ) ;
22+ [ GeneratedRegex ( @"^(\d+)\.(\d+)\.(\d+)" , RegexOptions . Multiline ) ]
23+ private static partial Regex VersionRegex ( ) ;
24+
25+ private static string ExeName => OperatingSystem . IsWindows ( ) ? "dotnet.exe" : "dotnet" ;
26+ private static readonly Lazy < List < string > > s_dotnetPathCandidates = new ( ( ) => ResolveDotnetPathCandidates ( ) ) ;
2627
2728 public static VisualStudioInstance ? GetInstance ( string dotNetSdkPath , bool allowQueryAllRuntimeVersions )
2829 {
@@ -38,7 +39,7 @@ internal static class DotNetSdkLocationHelper
3839 }
3940
4041 // Preview versions contain a hyphen after the numeric part of the version. Version.TryParse doesn't accept that.
41- Match versionMatch = VersionRegex . Match ( File . ReadAllText ( versionPath ) ) ;
42+ Match versionMatch = VersionRegex ( ) . Match ( File . ReadAllText ( versionPath ) ) ;
4243
4344 if ( ! versionMatch . Success )
4445 {
@@ -116,10 +117,9 @@ public static IEnumerable<VisualStudioInstance> GetInstances(string workingDirec
116117 static IEnumerable < string > GetAllAvailableSDKs ( bool allowAllDotnetLocations )
117118 {
118119 bool foundSdks = false ;
119- string [ ] ? resolvedPaths = null ;
120120 foreach ( string dotnetPath in s_dotnetPathCandidates . Value )
121121 {
122- int rc = NativeMethods . hostfxr_get_available_sdks ( exe_dir : dotnetPath , result : ( key , value ) => resolvedPaths = value ) ;
122+ int rc = NativeMethods . hostfxr_get_available_sdks ( exe_dir : dotnetPath , out string [ ] ? resolvedPaths ) ;
123123
124124 if ( rc == 0 && resolvedPaths != null )
125125 {
@@ -150,13 +150,7 @@ static IEnumerable<string> GetAllAvailableSDKs(bool allowAllDotnetLocations)
150150 string ? resolvedSdk = null ;
151151 foreach ( string dotnetPath in s_dotnetPathCandidates . Value )
152152 {
153- int rc = NativeMethods . hostfxr_resolve_sdk2 ( exe_dir : dotnetPath , working_dir : workingDirectory , flags : 0 , result : ( key , value ) =>
154- {
155- if ( key == NativeMethods . hostfxr_resolve_sdk2_result_key_t . resolved_sdk_dir )
156- {
157- resolvedSdk = value ;
158- }
159- } ) ;
153+ int rc = NativeMethods . hostfxr_resolve_sdk2 ( exe_dir : dotnetPath , working_dir : workingDirectory , flags : 0 , out resolvedSdk , out _ ) ;
160154
161155 if ( rc == 0 )
162156 {
@@ -178,7 +172,7 @@ static IEnumerable<string> GetAllAvailableSDKs(bool allowAllDotnetLocations)
178172 private static void ModifyUnmanagedDllResolver ( Action < AssemblyLoadContext > resolverAction )
179173 {
180174 // For Windows hostfxr is loaded in the process.
181- if ( ! IsWindows )
175+ if ( ! OperatingSystem . IsWindows ( ) )
182176 {
183177 var loadContext = AssemblyLoadContext . GetLoadContext ( Assembly . GetExecutingAssembly ( ) ) ;
184178 if ( loadContext != null )
@@ -197,9 +191,9 @@ private static IntPtr HostFxrResolver(Assembly assembly, string libraryName)
197191 }
198192
199193 string hostFxrLibName =
200- RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ?
194+ OperatingSystem . IsWindows ( ) ?
201195 "hostfxr.dll" :
202- RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) ? "libhostfxr.dylib" : "libhostfxr.so" ;
196+ OperatingSystem . IsMacOS ( ) ? "libhostfxr.dylib" : "libhostfxr.so" ;
203197 string hostFxrRoot = string . Empty ;
204198
205199 // Get the dotnet path candidates
@@ -237,12 +231,12 @@ private static IntPtr HostFxrResolver(Assembly assembly, string libraryName)
237231
238232 private static string SdkResolutionExceptionMessage ( string methodName ) => $ "Failed to find all versions of .NET Core MSBuild. Call to { methodName } . There may be more details in stderr.";
239233
240- private static IList < string > ResolveDotnetPathCandidates ( )
234+ private static List < string > ResolveDotnetPathCandidates ( )
241235 {
242236 var pathCandidates = new List < string > ( ) ;
243237 AddIfValid ( GetDotnetPathFromROOT ( ) ) ;
244238
245- string ? dotnetExePath = GetCurrentProcessPath ( ) ;
239+ string ? dotnetExePath = Environment . ProcessPath ;
246240 bool isRunFromDotnetExecutable = ! string . IsNullOrEmpty ( dotnetExePath )
247241 && Path . GetFileName ( dotnetExePath ) . Equals ( ExeName , StringComparison . InvariantCultureIgnoreCase ) ;
248242
@@ -254,9 +248,9 @@ private static IList<string> ResolveDotnetPathCandidates()
254248 string ? hostPath = Environment . GetEnvironmentVariable ( "DOTNET_HOST_PATH" ) ;
255249 if ( ! string . IsNullOrEmpty ( hostPath ) && File . Exists ( hostPath ) )
256250 {
257- if ( ! IsWindows )
251+ if ( ! OperatingSystem . IsWindows ( ) )
258252 {
259- hostPath = realpath ( hostPath ) ?? hostPath ;
253+ hostPath = File . ResolveLinkTarget ( hostPath , true ) ? . FullName ?? hostPath ;
260254 }
261255
262256 AddIfValid ( Path . GetDirectoryName ( hostPath ) ) ;
@@ -289,8 +283,6 @@ void AddIfValid(string? path)
289283 return dotnetPath ;
290284 }
291285
292- private static string ? GetCurrentProcessPath ( ) => Environment . ProcessPath ;
293-
294286 private static string ? GetDotnetPathFromPATH ( )
295287 {
296288 string ? dotnetPath = null ;
@@ -314,19 +306,6 @@ void AddIfValid(string? path)
314306 return dotnetPath ;
315307 }
316308
317- /// <summary>
318- /// This native method call determines the actual location of path, including
319- /// resolving symbolic links.
320- /// </summary>
321- private static string ? realpath ( string path )
322- {
323- IntPtr ptr = NativeMethods . realpath ( path , IntPtr . Zero ) ;
324- string ? result = Marshal . PtrToStringAuto ( ptr ) ;
325- NativeMethods . free ( ptr ) ;
326-
327- return result ;
328- }
329-
330309 private static string ? FindDotnetPathFromEnvVariable ( string environmentVariable )
331310 {
332311 string ? dotnetPath = Environment . GetEnvironmentVariable ( environmentVariable ) ;
@@ -347,9 +326,9 @@ private static void SetEnvironmentVariableIfEmpty(string name, string value)
347326 string fullPathToDotnetFromRoot = Path . Combine ( dotnetPath , ExeName ) ;
348327 if ( File . Exists ( fullPathToDotnetFromRoot ) )
349328 {
350- if ( ! IsWindows )
329+ if ( ! OperatingSystem . IsWindows ( ) )
351330 {
352- fullPathToDotnetFromRoot = realpath ( fullPathToDotnetFromRoot ) ?? fullPathToDotnetFromRoot ;
331+ fullPathToDotnetFromRoot = File . ResolveLinkTarget ( fullPathToDotnetFromRoot , true ) ? . FullName ?? fullPathToDotnetFromRoot ;
353332 return File . Exists ( fullPathToDotnetFromRoot ) ? Path . GetDirectoryName ( fullPathToDotnetFromRoot ) : null ;
354333 }
355334
0 commit comments