private static void FindExtension() { if (_looked) { return; } bool hasDependencyContext; try { hasDependencyContext = DependencyContext.Default != null; } catch (Exception ex) // Work around dotnet/core-setup#4556 { Debug.Fail(ex.ToString()); hasDependencyContext = false; } if (hasDependencyContext) { var candidateAssets = new Dictionary <(string, string), int>(); var rid = RuntimeInformation.RuntimeIdentifier; var rids = DependencyContext.Default !.RuntimeGraph.FirstOrDefault(g => g.Runtime == rid)?.Fallbacks.ToList() ?? new List <string?>(); rids.Insert(0, rid); foreach (var library in DependencyContext.Default.RuntimeLibraries) { foreach (var group in library.NativeLibraryGroups) { foreach (var file in group.RuntimeFiles) { if (string.Equals( Path.GetFileName(file.Path), "mod_spatialite" + SharedLibraryExtension, StringComparison.OrdinalIgnoreCase)) { var fallbacks = rids.IndexOf(group.Runtime); if (fallbacks != -1 && library.Path is not null) { candidateAssets.Add((library.Path, file.Path), fallbacks); } } } } } var assetPath = candidateAssets.OrderBy(p => p.Value) .Select(p => p.Key).FirstOrDefault(); if (assetPath != default) { string?assetDirectory; if (File.Exists(Path.Combine(AppContext.BaseDirectory, assetPath.Item2))) { // NB: This enables framework-dependent deployments assetDirectory = Path.Combine( AppContext.BaseDirectory, Path.GetDirectoryName(assetPath.Item2.Replace('/', Path.DirectorySeparatorChar)) !); } else { string?assetFullPath = null; var probingDirectories = ((string)AppDomain.CurrentDomain.GetData("PROBING_DIRECTORIES") !) .Split(Path.PathSeparator); foreach (var directory in probingDirectories) { var candidateFullPath = Path.Combine( directory, (assetPath.Item1 + "/" + assetPath.Item2).Replace('/', Path.DirectorySeparatorChar)); if (File.Exists(candidateFullPath)) { assetFullPath = candidateFullPath; } } Check.DebugAssert(assetFullPath != null, "assetFullPath is null"); assetDirectory = Path.GetDirectoryName(assetFullPath); } Check.DebugAssert(assetDirectory != null, "assetDirectory is null"); // GetEnvironmentVariable can sometimes return null when there is a race condition // with another thread setting it. Therefore we do a bit of back off and retry here. // Note that the result can be null if no path is set on the system. var delay = 1; var currentPath = Environment.GetEnvironmentVariable(PathVariableName !); while (currentPath == null && delay < 1000) { Thread.Sleep(delay); delay *= 2; currentPath = Environment.GetEnvironmentVariable(PathVariableName !); } if (currentPath == null || !currentPath.Split(Path.PathSeparator).Any( p => string.Equals( p.TrimEnd(Path.DirectorySeparatorChar), assetDirectory, StringComparison.OrdinalIgnoreCase))) { Environment.SetEnvironmentVariable( PathVariableName !, assetDirectory + Path.PathSeparator + currentPath); } } } _looked = true; }