无法加载sqlce.dll (翻译)

无法加载sqlce.dll

原文:Can’t load sqlce dll

作者:Laxmi Narsimha Rao ORUGANTI

翻译:flyjimi

 

SQL Server CE/Compact 使用Windows API LoadLibraryPlatform Builder WinCE Win32)加载DLL文件。当LoadLibrary加载任何SQL CE dll失败时,会抛出错误“无法加载sqlce.dll”。现在,我们来讨论一下LoadLibrary为什么会失败。

 

1) 虚拟内存太低而不能加载dll

2) 缺少依赖的dll

3) Windows CE LoadLibrary 执行了危险的操作。

 

关于第()点,请对DLL运行depends.exe,确保你的镜像包含了所有必需的依赖dll。注意,SQL Server CE 依赖于OLEAUTO.DLLOLE.DLL。一些自定义的镜像可能没有选择Platform Builder catalog支持COM,因此系统加载模块失败。

关于第(1)点和第(3)点,请完整阅读KB Article 326163,我会强调这篇文章中的一些事项。

 

摘录:

当一个进程加载一个dll时,Windows CE在每个进程的地址空间保留这个dll的地址空间。使用同一个dll的多个进程在每个进程中相同的相对地址共享这个dll。如果你的应用程序没有使用同一个dll,它就不能使用为这个dll保留的内存。换句话说,Windows CE 不会把一个基于RAMdll映射到某个地址,如果这个地址已经被另一个进程映射了另一个dll。例如,如果进程A加载dll X到地址0x00970000Windows CE不会把进程B中的dll Y映射到地址空间0x00970000。取代的做法是,Windows CE根据dll Y的大小,找下一个可用的低位地址。所以,如果dll Y的大小不超过128KBWindows CE 会选择0x00950000,如果这个地址对进程B可用。因为Windows CE允许进程共享一个公共的dllWindows CE不允许两个不同的进程在各自相同的相对地址中加载两个不同的dll

 

这段话的意思是,如果有不同的进程加载了很多dll,而你的进程最后加载,由于很多的地址空间被保留,你的进程的LoadLibrary可能会失败。

文章建议的解决办法:

摘录:

如果你确定你的应用程序是因为缺少地址空间而不能加载dll,考虑一下下面的办法:

1. 如果你的应用程序是使用Microsoft CMicrosoft C++实现的,或者你的嵌入式VB应用程序使用了定制的dll,确定你是否在使用VirtualAlloc函数时加上了MEM_TOP_DOWN标记。如果你使用了这个标记,就会尽可能从高位分配内存,这会导致dll不能加载。VirtualAlloc函数不应该使用这个标记。

2. 如果你的应用程序使用了很多的定制dll,把代码合并到一两个dll。一个dll占用的最小地址空间是64KB。因此,如果你的程序设计成有30个大小为810KBdll,你就浪费了1620KB(译者注:(64-10*30=1620)的地址空间。

3. 把应用程序分解成几个进程。使用一个进程加载一组dll,使用另一个进程加载另一组dll。(根据应用程序的设计,这可能不现实。如果两个进程必须同时运行,使用两个单独的进程就没有什么帮助。)

4.首次启动应用程序时就加载所有基本的dll如果可能,就保持dll已加载。在你的应用程序做这个改变后,观察是否会导致内存分配或其它进程无法工作。如果会(导致其他进程无法工作),你必须重新设计你的应用程序,以减小dll或内存使用。

5.重新设计应用程序,全面减少内存使用。只使用基本的dll,并且一旦使用完就卸载。最小化堆的使用,因为这决定了能加载多少dll。注意,当你把ActiveX对象的变量设置为NothingActiveX对象的引用不会卸载。

 

(4)个方法是很容易尝试的,而且对我们一些客户很有效。另外,基于COM的应用程序运行时,尽量使用CoFreeUnusedLibraries Win32WindCEAPI,卸载不用的模块。

 

致谢,

Laxmi Narsimha Rao ORUGANTI

 

发布日期:20071026 下午8:01,星期五 SQLCEBLOG 

归档: Troubleshooting

 

 

你可能感兴趣的:(C#,dll,windows,microsoft,sql,server,wince,api)