我对Assembly.LoadFrom
的行为感到困惑。在我的应用程序中,我将Assembly.LoadFrom
称为.NET .exe
并使用EntryPoint.Invoke
启动它(这种奇怪的方法对于在非Windows上构建启动程序应用程序非常有用平台)。
我原以为由于assemblyFile
位于不同的文件夹中,因此无法找到与其位于同一文件夹中的某些托管 .dll
依赖项。但它奏效了;它没有失败......
当我调用Assembly.LoadFrom(assemblyFile)
时,它会检查包含assemblyFile
的文件夹,以查找assemblyFile
的托管依赖项。我没想到这一点。如果该程序集具有非托管依赖项(例如DllImport
)会发生什么情况,它是否仍会搜索同一目录?这个行为框架是否具体?
答案 0 :(得分:8)
Assembly
与加载未标记的库无关。非托管库的加载是DllImport
调用是多么懒惰(在第一次调用之前不会加载)。
DllImport反过来(在.NET中,我不知道Mono在其他平台上做了什么)在Windows上调用LoadLibary
。 LoadLibary
有a known set of rules表示如何解决它的依赖关系:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
。如果不满足这两点且启用了SafeDllSearchMode
(默认情况下适用于XP SP2及更新版本),则使用以下顺序
因此,要回答您的问题,在查找非托管程序集时,不会搜索托管程序集所在的目录,只会搜索加载托管程序集的应用程序目录。
然而,所有的希望都没有丢失,你可以调用SetDLLDirectory
并添加托管程序集的文件夹,它会在搜索中包含它,在查找非托管DLL时,它会将搜索顺序更改为
如果您需要添加多个文件夹进行搜索,请参阅AddDllDirectory
上的MSDN文档,了解允许多个搜索目录所需的步骤。
答案 1 :(得分:4)
.NET特定配置都不会影响非托管DLL的定位方式。无论CLR如何找到托管程序集,正常的操作系统搜索规则都有效。 Windows上的底层OS调用是LoadLibrary(),这是一种不支持改变搜索规则本身的winapi函数。您可以指定完整路径名称以避免搜索,但这在pinvoke中几乎不可行。
如果这是一个问题,那么你必须编写显式代码来帮助操作系统找到文件。常见的技术是调整SetDllDirectory(),使用Environment.SetEnvironmentVariable()更改PATH环境变量,并通过分配Environment.CurrentDirectory
来更改默认目录。