ASP.Net中的DllImport如何查找DLL?

ASP.Net是如何为本地DLL设置搜索路径的? 我需要能够在我自己的代码中复制逻辑。

更多背景:我维护一个托管的库(比如Managed.DLL),它包装一个本地库(称为Native.DLL),该库本身又使用另一个本地DLL(如Driver.DLL)。 到目前为止,Managed.DLL一直使用.Net的DllImport属性从Native.DLL导入函数,但现在我必须将其更改为手动编码调用LoadLibrary和GetProcAddress以获得更多控制; 特别是,我需要能够调用FreeLibrary来卸载Native.DLL,并且当通过DllImport加载Native.DLL时,我无法执行此操作。

问题来了:虽然只有DllImport(“Native.DLL”)足以查找Native.DLL和Driver.DLL,但在ASP中使用Managed.DLL时,调用LoadLibrary(“Native.DLL”)失败,并显示ERROR_FILE_NOT_FOUND .Net应用程序,因为包含Managed.DLL的目录不在本机代码DLL的搜索路径中。

我的第一个想法是使用Assembly.GetExecutingAssembly()。位置,然后发出带有完整路径的LoadLibrary调用,但是Native.DLL无法找到Driver.DLL,因为包含它们的目录仍然不在搜索路径中。

我可以通过使用Assembly.GetExecutingAssembly()。位置值来设置本机DLL搜索路径与SetDllDirectory,但这有两个主要缺点:

1)SetDllDirectory更改全局WinAPI设置,并可能干扰同样使用本机代码DLL的同一ASP.Net工作进程中的其他代码; 我也已经证实,使用DllImport属性不会混淆这个设置,所以现在改变它可能确实会破坏以前工作的东西。

2)它仍然不适用于在Visual Studio中调试ASP.Net应用程序,因为VS会将受管资源复制到临时目录中,但会将本机DLL留在项目构建目录中,因此它们会在调试的不同位置结束会话(并且每个调试会话都会擦除临时目录,因此手动将本机DLL复制到它中也不起作用;我必须将本机DLL复制到IIS的目录中以便调试会话找到它们,这显然是不可接受的解决方案)。

我真的想在这里做兼容的事情,但到目前为止还没有能够找出这是什么,经过几天的无果搜索任何指针将不胜感激。


回答我自己的问题:

1)关于复制Managed.DLL的关键字我错过了“影子复制”(詹姆斯舒伯特解释它比我见过的任何微软官方文档都好),诀窍是使用Assembly.CodeBase而不是Assembly.Location ,因为前者给出了Managed.DLL的原始位置,后者给出了影子副本的位置(John Sibly和Sneal共享了漂亮的代码片段以从Assembly.CodeBase的URI中提取目录名称)。

2)使本地DLL的依赖性可用的方法是在需要之前使用LoadLibrary显式加载它们(并且因为这增加了它们的引用计数,并且在完成时使用FreeLibrary释放它们)。

所以,加载顺序是

string dir = Assembly.GetExecutingAssembly().CodeBase;
dir = new Uri(dir).LocalPath;
dir = Path.GetDirectoryName(dir);
IntPtr driver = LoadLibrary(dir + Path.DirectorySeparatorChar + "Driver.DLL");
IntPtr managed = LoadLibrary(dir + Path.DirectorySeparatorChar + "Managed.DLL");

和卸载顺序

FreeLibrary(managed);
FreeLibrary(driver);

(还要注意LoadLibraryFreeLibrary调用的顺序)。

链接地址: http://www.djcxy.com/p/7749.html

上一篇: How does DllImport in ASP.Net look for the DLL?

下一篇: Inno Setup 5.5.4(a) under Windows 7 with mistake "cannot import dll"