无法加载sqlce.dll
原文:Can’t load sqlce dll
作者:Laxmi Narsimha Rao ORUGANTI
翻译:flyjimi
SQL Server CE/Compact 使用Windows API LoadLibrary(Platform Builder 、WinCE 或 Win32)加载DLL文件。当LoadLibrary加载任何SQL CE dll失败时,会抛出错误“无法加载sqlce.dll”。现在,我们来讨论一下LoadLibrary为什么会失败。
1) 虚拟内存太低而不能加载dll。
2) 缺少依赖的dll。
3) Windows CE LoadLibrary 执行了危险的操作。
关于第(2)点,请对DLL运行depends.exe,确保你的镜像包含了所有必需的依赖dll。注意,SQL Server CE 依赖于OLEAUTO.DLL,OLE.DLL。一些自定义的镜像可能没有选择Platform Builder catalog支持COM,因此系统加载模块失败。
关于第(1)点和第(3)点,请完整阅读KB Article 326163,我会强调这篇文章中的一些事项。
摘录:
当一个进程加载一个dll时,Windows CE在每个进程的地址空间保留这个dll的地址空间。使用同一个dll的多个进程在每个进程中相同的相对地址共享这个dll。如果你的应用程序没有使用同一个dll,它就不能使用为这个dll保留的内存。换句话说,Windows CE 不会把一个基于RAM的dll映射到某个地址,如果这个地址已经被另一个进程映射了另一个dll。例如,如果进程A加载dll X到地址0x00970000,Windows CE不会把进程B中的dll Y映射到地址空间0x00970000。取代的做法是,Windows CE根据dll Y的大小,找下一个可用的低位地址。所以,如果dll Y的大小不超过128KB,Windows CE 会选择0x00950000,如果这个地址对进程B可用。因为Windows CE允许进程共享一个公共的dll,Windows CE不允许两个不同的进程在各自相同的相对地址中加载两个不同的dll。
这段话的意思是,如果有不同的进程加载了很多dll,而你的进程最后加载,由于很多的地址空间被保留,你的进程的LoadLibrary可能会失败。
文章建议的解决办法:
摘录:
如果你确定你的应用程序是因为缺少地址空间而不能加载dll,考虑一下下面的办法:
1. 如果你的应用程序是使用Microsoft C或Microsoft C++实现的,或者你的嵌入式VB应用程序使用了定制的dll,确定你是否在使用VirtualAlloc函数时加上了MEM_TOP_DOWN标记。如果你使用了这个标记,就会尽可能从高位分配内存,这会导致dll不能加载。VirtualAlloc函数不应该使用这个标记。
2. 如果你的应用程序使用了很多的定制dll,把代码合并到一两个dll。一个dll占用的最小地址空间是64KB。因此,如果你的程序设计成有30个大小为8到10KB的dll,你就浪费了1620KB(译者注:(64-10)*30=1620)的地址空间。
3. 把应用程序分解成几个进程。使用一个进程加载一组dll,使用另一个进程加载另一组dll。(根据应用程序的设计,这可能不现实。如果两个进程必须同时运行,使用两个单独的进程就没有什么帮助。)
4.首次启动应用程序时就加载所有基本的dll。如果可能,就保持dll已加载。在你的应用程序做这个改变后,观察是否会导致内存分配或其它进程无法工作。如果会(导致其他进程无法工作),你必须重新设计你的应用程序,以减小dll或内存使用。
5.重新设计应用程序,全面减少内存使用。只使用基本的dll,并且一旦使用完就卸载。最小化堆的使用,因为这决定了能加载多少dll。注意,当你把ActiveX对象的变量设置为Nothing,ActiveX对象的引用不会卸载。
第(4)个方法是很容易尝试的,而且对我们一些客户很有效。另外,基于COM的应用程序运行时,尽量使用CoFreeUnusedLibraries (Win32、WindCE)API,卸载不用的模块。
致谢,
Laxmi Narsimha Rao ORUGANTI
发布日期: 2007 年 10 月 26 日 下午8:01,星期五 ,SQLCEBLOG
归档: Troubleshooting