rewrite fallback assembly resolution
* SMAPI now also searches the root game folder for unresolved assemblies. This fixes an issue resolving the game DLL when the player's DLL version doesn't match the one used to compile SMAPI. * The DLL search folders are now scanned once and cached to avoid repeated iterations on startup.
This commit is contained in:
parent
85f8631bee
commit
95f4513727
|
@ -1,6 +1,9 @@
|
||||||
← [README](README.md)
|
← [README](README.md)
|
||||||
|
|
||||||
# Release notes
|
# Release notes
|
||||||
|
## Upcoming release
|
||||||
|
* Fixed Linux/macOS launch error in 3.13.3.
|
||||||
|
|
||||||
## 3.13.3
|
## 3.13.3
|
||||||
Released 16 January 2022 for Stardew Valley 1.5.6 or later.
|
Released 16 January 2022 for Stardew Valley 1.5.6 or later.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -16,7 +17,10 @@ namespace StardewModdingAPI
|
||||||
** Fields
|
** Fields
|
||||||
*********/
|
*********/
|
||||||
/// <summary>The absolute path to search for SMAPI's internal DLLs.</summary>
|
/// <summary>The absolute path to search for SMAPI's internal DLLs.</summary>
|
||||||
internal static readonly string DllSearchPath = EarlyConstants.InternalFilesPath;
|
private static readonly string DllSearchPath = EarlyConstants.InternalFilesPath;
|
||||||
|
|
||||||
|
/// <summary>The assembly paths in the search folders indexed by assembly name.</summary>
|
||||||
|
private static Dictionary<string, string> AssemblyPathsByName;
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
|
@ -57,16 +61,36 @@ namespace StardewModdingAPI
|
||||||
/// <param name="e">The event arguments.</param>
|
/// <param name="e">The event arguments.</param>
|
||||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e)
|
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e)
|
||||||
{
|
{
|
||||||
|
// cache assembly paths by name
|
||||||
|
if (Program.AssemblyPathsByName == null)
|
||||||
|
{
|
||||||
|
Program.AssemblyPathsByName = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
foreach (string searchPath in new[] { EarlyConstants.ExecutionPath, Program.DllSearchPath })
|
||||||
|
{
|
||||||
|
foreach (string dllPath in Directory.EnumerateFiles(searchPath, "*.dll"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string curName = AssemblyName.GetAssemblyName(dllPath).Name;
|
||||||
|
if (curName != null)
|
||||||
|
Program.AssemblyPathsByName[curName] = dllPath;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AssemblyName name = new AssemblyName(e.Name);
|
string searchName = new AssemblyName(e.Name).Name;
|
||||||
foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll"))
|
return searchName != null && Program.AssemblyPathsByName.TryGetValue(searchName, out string assemblyPath)
|
||||||
{
|
? Assembly.LoadFrom(assemblyPath)
|
||||||
if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.OrdinalIgnoreCase))
|
: null;
|
||||||
return Assembly.LoadFrom(dll.FullName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue