diff --git a/README.md b/README.md index debcfa2..83220bb 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,10 @@ let info = DotnetEnvironmentInfo.Get () // or, if you already know a path to the `dotnet` executable... let info = DotnetEnvironmentInfo.Get "/path/to/dotnet" ``` + +## Troubleshooting + +If you have a *very* strange setup, we may be unable to locate the `libhostfxr` library we use to find the runtimes. +In that case, you can supply the environment variable `WOOFWARE_DOTNET_LOCATOR_LIBHOSTFXR`, +which should be a full path to a `libhostfxr` DLL on your system. +(Normally this is in `/usr/share/dotnet/host/fxr/{runtime}/libhostfxr.so`; you must make sure your version is from runtime 6 or greater, because the required symbols were not added until then.) diff --git a/WoofWare.DotnetRuntimeLocator/DotnetEnvironmentInfo.cs b/WoofWare.DotnetRuntimeLocator/DotnetEnvironmentInfo.cs index d917d1f..b934e98 100644 --- a/WoofWare.DotnetRuntimeLocator/DotnetEnvironmentInfo.cs +++ b/WoofWare.DotnetRuntimeLocator/DotnetEnvironmentInfo.cs @@ -26,6 +26,16 @@ public record DotnetEnvironmentInfo( { private static readonly Lazy HostFxr = new(() => { + switch (Environment.GetEnvironmentVariable("WOOFWARE_DOTNET_LOCATOR_LIBHOSTFXR")) + { + case null: + break; + case var s: + { + return new FileInfo(s); + } + } + // First, we might be self-contained: try and find it next to us. var selfContainedAttempt = Directory.GetParent(Assembly.GetExecutingAssembly().Location); if (selfContainedAttempt != null) @@ -42,7 +52,15 @@ public record DotnetEnvironmentInfo( var parent3 = parent2.Parent ?? throw new Exception("Unable to locate the host/fxr directory in the .NET runtime"); var fxrDir = new DirectoryInfo(Path.Combine(parent3.FullName, "host", "fxr")); - return fxrDir.EnumerateDirectories().First().EnumerateFiles("*hostfxr*").First(); + Func isAcceptableName = + di => + { + // Until net6, libhostfxr did not contain the entrypoint we use, and I can't be bothered to reimplement + // it on those runtimes. I'm just going to assume you have no runtimes earlier than 3 installed. + return !di.Name.StartsWith("3.", StringComparison.Ordinal) && + !di.Name.StartsWith("5.", StringComparison.Ordinal); + }; + return fxrDir.EnumerateDirectories().First(isAcceptableName).EnumerateFiles("*hostfxr*").First(); }); private static FileInfo ResolveAllSymlinks(FileInfo f)