Assembly.LoadFrom 没有从文件夹加载 DLL

Assembly.LoadFrom is not loading DLL from folder

我构建了一个应用程序,该应用程序需要访问三个 DLL 以实现可选功能。 因为它是可选的,所以我不提供这 3 个 DLL,并让用户 select 如果他想要或不想拥有它。 但是因为我实际上是在代码中使用 DLL,所以我需要引用它们(通过 nuget)。

问题是,如果这 3 个 DLL 存储在与主要可执行文件所在的文件夹不同的文件夹中,应用程序将无法访问它们。

SharpDX.Direct3D11.dll
SharpDX.dll
SharpDX.DXGI.dll

我已经尝试手动调用 Assembly.LoadFrom(path) 但没有成功。
奇怪的是应用程序无法加载其中之一:

*** Assembly Binder Log Entry  (27/02/2020 @ 10:51:36) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable  C:\Program Files (x86)\MyApp\MyApp.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
 (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/MyApp/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyApp.exe
Calling assembly : MyApp, Version=2.21.1.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.EXE.
LOG: All probing URLs attempted and failed.



*** Assembly Binder Log Entry  (27/02/2020 @ 10:51:36) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable  C:\Program Files (x86)\MyApp\MyApp.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
 (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/MyApp/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyApp.exe
Calling assembly : MyApp, Version=2.21.1.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.EXE.
LOG: All probing URLs attempted and failed.

试图加载三个 DLL 的代码是这样的,它在任何对 SharpDX 库的调用或引用出现之前运行,我调试并正常执行这些行:

public static void LoadSharpDx()
{
    var realPath = UserSettings.All.SharpDxLocationFolder ?? "";

    //In order to get the correct location, I need to combine the current base directory with the relative path.
    if (!string.IsNullOrWhiteSpace(UserSettings.All.SharpDxLocationFolder) && !Path.IsPathRooted(UserSettings.All.SharpDxLocationFolder))
        realPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, UserSettings.All.SharpDxLocationFolder.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));

    if (string.IsNullOrEmpty(realPath) || realPath == ".")
        return;

    //The realPath is C:\Users\nicke\Desktop\Dll  
    //So, it's correct.

    Assembly.LoadFrom(Path.Combine(realPath, "SharpDX.dll"));
    Assembly.LoadFrom(Path.Combine(realPath, "SharpDX.Direct3D11.dll"));
    Assembly.LoadFrom(Path.Combine(realPath, "SharpDX.DXGI.dll"));

    //Throws a different error.
    //Assembly.Load(Path.Combine(realPath, "SharpDX.dll"));
    //Assembly.Load(Path.Combine(realPath, "SharpDX.Direct3D11.dll"));
    //Assembly.Load(Path.Combine(realPath, "SharpDX.DXGI.dll"));
}

在分析 ProcMon 时,我可以看到应用程序能够找到并加载文件夹中的 DLL。

所以,这是怎么回事?

为什么无法加载 SharpDX.DXGI 库?

所以,我解释错了 Assembly.LoadFrom() 在做什么。

最后,我不得不使用 CurrentDomain.AssemblyResolve 事件:

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    try
    {
        var assemblyName = args.Name.Split(',').First();

        if (!assemblyName.StartsWith("SharpDX"))
            return null;

        //Simply converts relative paths to full paths in order to
        //prevent getting the wrong path when the app is loaded from a
        //link or "Open with..." commands.
        var path = Other.AdjustPath(UserSettings.All.SharpDxLocationFolder ?? "");

        return Assembly.LoadFrom(System.IO.Path.Combine(path, $"{assemblyName}.dll"));
    }
    catch (Exception e)
    {
        LogWriter.Log(e, "Error loading assemblies");
        return null;
    }
}