Assembly.LoadFrom如何解决非托管依赖项?

Mr.*_*ith 2 .net c# dllimport

我对这种行为感到困惑Assembly.LoadFrom.在我的应用程序中,我调用Assembly.LoadFrom.NET .exe并使用它来启动它EntryPoint.Invoke(这种奇怪的方法对于在非Windows平台上构建启动器应用程序非常有用).

我曾假设,因为它assemblyFile位于不同的文件夹中,所以它无法找到与它位于同一文件夹中的某些托管 .dll依赖项.但它奏效了; 它并没有失败......

这样看来,当我打电话Assembly.LoadFrom(assemblyFile),它包含检查的文件夹assemblyFile进行管理的依赖关系assemblyFile.我没想到这一点.如果该程序集具有非托管依赖项(例如a DllImport)会发生什么情况,它仍会搜索同一目录吗?这个行为框架是否具体?

Sco*_*ain 9

Assembly与加载非标记库无关.非托管库的加载是DllImport什么是懒惰的调用(直到第一次调用才加载).

DllImport反过来(在.NET中,我不知道Mono在其他平台上做了什么)LoadLibary在Windows 上调用.LoadLibary一组已知的规则来解决它的依赖关系:

  • 如果已在内存中加载具有相同模块名称的DLL,则系统将使用加载的DLL,无论它在哪个目录中.系统不会搜索DLL.
  • 如果DLL位于运行应用程序的Windows版本的已知DLL列表中,则系统将使用其已知DLL(以及已知DLL的相关DLL,如果有)的副本.系统不搜索DLL.有关当前系统上已知DLL的列表,请参阅以下注册表项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.

如果未满足这两点并且SafeDllSearchMode已启用(默认情况下为XP SP2及更高版本),则使用以下顺序

  1. 加载应用程序的目录.
  2. 系统目录.使用GetSystemDirectory函数获取此目录的路径.
  3. 16位系统目录.没有函数可以获取此目录的路径,但会搜索它.
  4. Windows目录.使用GetWindowsDirectory函数获取此目录的路径.
  5. 当前目录.
  6. PATH环境变量中列出的目录.请注意,这不包括App Paths注册表项指定的每个应用程序路径.计算DLL搜索路径时不使用App Paths键.

因此,要回答您的问题,在查找非托管程序集时,不会搜索托管程序集所在的目录,也不会搜索加载托管程序集的应用程序的目录.

但是,所有希望都不会丢失,您可以调用SetDLLDirectory并添加托管程序集的文件夹,并在查找非托管DLL时将其包含在搜索中,它会将搜索顺序更改为

  1. 加载应用程序的目录.
  2. lpPathName参数指定的目录(在SetDLLDirectory调用中).
  3. 系统目录.使用GetSystemDirectory函数获取此目录的路径.该目录的名称是System32.
  4. 16位系统目录.没有函数可以获取此目录的路径,但会搜索它.该目录的名称是System.
  5. Windows目录.使用GetWindowsDirectory函数获取此目录的路径.
  6. PATH环境变量中列出的目录.

如果您需要添加多个文件夹进行搜索,请参阅MSDN以获取有关AddDllDirectory允许多个搜索目录所需步骤的文档.