我对这种行为感到困惑Assembly.LoadFrom
.在我的应用程序中,我调用Assembly.LoadFrom
.NET .exe
并使用它来启动它EntryPoint.Invoke
(这种奇怪的方法对于在非Windows平台上构建启动器应用程序非常有用).
我曾假设,因为它assemblyFile
位于不同的文件夹中,所以它无法找到与它位于同一文件夹中的某些托管 .dll
依赖项.但它奏效了; 它并没有失败......
这样看来,当我打电话Assembly.LoadFrom(assemblyFile)
,它包含检查的文件夹assemblyFile
进行管理的依赖关系assemblyFile
.我没想到这一点.如果该程序集具有非托管依赖项(例如a DllImport
)会发生什么情况,它仍会搜索同一目录吗?这个行为框架是否具体?
这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及更高版本),则使用以下顺序
加载应用程序的目录.
系统目录.使用GetSystemDirectory函数获取此目录的路径.
16位系统目录.没有函数可以获取此目录的路径,但会搜索它.
Windows目录.使用GetWindowsDirectory函数获取此目录的路径.
当前目录.
PATH环境变量中列出的目录.请注意,这不包括App Paths注册表项指定的每个应用程序路径.计算DLL搜索路径时不使用App Paths键.
因此,要回答您的问题,在查找非托管程序集时,不会搜索托管程序集所在的目录,也不会搜索加载托管程序集的应用程序的目录.
但是,所有希望都不会丢失,您可以调用SetDLLDirectory
并添加托管程序集的文件夹,并在查找非托管DLL时将其包含在搜索中,它会将搜索顺序更改为
加载应用程序的目录.
lpPathName参数指定的目录(在SetDLLDirectory调用中).
系统目录.使用GetSystemDirectory函数获取此目录的路径.该目录的名称是System32.
16位系统目录.没有函数可以获取此目录的路径,但会搜索它.该目录的名称是System.
Windows目录.使用GetWindowsDirectory函数获取此目录的路径.
PATH环境变量中列出的目录.
如果您需要添加多个文件夹进行搜索,请参阅MSDN以获取有关AddDllDirectory
允许多个搜索目录所需步骤的文档.