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;
}
}
我构建了一个应用程序,该应用程序需要访问三个 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;
}
}