如何让显式加载失败如同隐式加载失败一样,获得系统所能给予的加载失败原因?

winthegame 2006-02-21 03:30:57
一般而言,隐式加载如果加载出错的话,系统都会给予提示。

例如 aaa.Exe隐式加载了bbb.dll, 而bbb.dll同样隐式加载了ccc.dll,如果ccc.dll在搜索路径上不能找到,那么运行aaa.Exe, 加载bbb.dll就会失败,系统会给予提示:
---------------------------
aaa.exe - 无法找到 DLL
--------------------------
无法找到动态链接库 ccc.dll 于指定的路径 C:\WINNT\system32;C:\WINNT\system;C:\WINNT; 上。
---------------------------
确定
---------------------------

而如果aaa.Exe显式加载了bbb.dll呢?那么,LoadLibrary 就会失败,使用GetLastError,得到错误代码126--找不到指定的模块,却无法获得如上的加载失败原因。这就让人一时摸不着头脑了....

我的问题就是:如何在显式加载失败时,使之类似隐式加载一般,报告出加载失败的具体原因?解决此问题也许只是一个API,也许是一大段代码,总之,烦请指教。
...全文
458 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
winthegame 2006-03-16
  • 打赏
  • 举报
回复
向来不喜欢拖问题,只不过感觉的确没有找到更好的方法,其实使用LoadLibrary时弹出系统错误框的方法很简单,就是SetErrorMode而已,但要把那个系统框的描述获得到程序中似乎还是没有什么好办法,什么都自己做倒是能做--但总觉得不是好办法,一定还有更好的法子....,算了吧,实在没有太多空多想了,谢谢各位参与,结贴!
wangk 2006-02-24
  • 打赏
  • 举报
回复
to winthegame(120斤重的大青蛙)
好像没有什么好的方法,你总不能让咱村前的小土路跑宝马之流的车子吧。交通不靠走是不成啦。只能请MS修路了……
shootingstars 2006-02-24
  • 打赏
  • 举报
回复
关注。
我原来以为是因为采用隐式加载dll时会将所有这个dll与之相关的dll一起加入导出表,但是看来似乎不是(使用Depends看)。。。
wangk 2006-02-22
  • 打赏
  • 举报
回复
2.如果不想用LoadLibrary,其实可以用PE文件分析,PE格式里有记录可执行的类型、入口等……
wangk 2006-02-22
  • 打赏
  • 举报
回复
1.肯定要用递归,就像Depands工具一样。
2.如果3用LoadLibrary判断呢?,如果任意文件改名为那个需要的文件还是能知道不能加载成功。
winthegame 2006-02-22
  • 打赏
  • 举报
回复
LookSail(老得牙都掉了还在学)
GetLastError的提示非常之不足,以至于此类问题如果是显式加载获得的错误提示信息之少,让人浑摸不着头脑,如果这是终极提示,那么就有问题了。
我刚才写完贴,随便测试一下,分别采取三个方法来试验:
1-删去隐式加载库
GetLastError报告:找不到指定的模块。
隐式同帖子正文。
2-将一个其他的动态库改名成此隐式库
GetLastError报告 127:找不到指定的程序。 (汗)
隐式报告:
---------------------------
aaa.exe - 无法找到入口
---------------------------
无法定位程序输入点 func1 于动态链接库 ccc.dll 上。
---------------------------
确定
---------------------------
3.随便拷贝一个文本文件改名成此隐式文件。
GetLastError报告193:%1 不是合法的 Win32 应用程序。

隐式加载报告

---------------------------
aaa.exe - 损坏的图像
---------------------------
应用程序或 DLL C:\Test\Debug\ccc.dll 为无效的 Windows 映像。请再检测一遍您的安装盘。
---------------------------
确定
---------------------------

可诊断性,两下相较,一目了然。
winthegame 2006-02-22
  • 打赏
  • 举报
回复
wangk(倒之):
汗,如果真的需要象2一般,"读取dll的隐式加载需要的文件"的话,那么恐怕还要考虑递归---因为如果此dll隐式加载需要的dll可能也隐式加载了一些dll, 更何况如果将任意文件改名为那个需要的文件,你的方法也不适用--查找文件是能够找到的,而LoadLibrary仍然会报错,而且如果以上两点交给系统帮你做--既是不采取显式加载而是隐式加载,系统均能准确的将错误结论得出,所以说仍然没有找到思路呢......
wangk 2006-02-22
  • 打赏
  • 举报
回复
Load出错后:
1.判断该DLL是否存在
2.读取Dll的隐式加载需要的文件(PE格式分析)
3.SearchPath在当前文件夹和系统文件夹查找Dll的隐式加载需要的文件是否存在。
LookSail 2006-02-22
  • 打赏
  • 举报
回复
GetLastError应该是终极方法了,你试下把dll都放到windows的系统目录再运行
zephyr007 2006-02-22
  • 打赏
  • 举报
回复
关注
winthegame 2006-02-22
  • 打赏
  • 举报
回复
wangk(倒之):
之前忙事,再加之再想其他方法,故而没有回答你,你的方法不能说行不通,但是用这种“交通基本靠走,娱乐基本靠手”的方法未免过于繁琐,等这段东西出来,那么倒之版的Depands 也出来了,其实只是需要获知系统信息而已,恐怕还有其他方法,我再想想了......,如果有新的想法,请提示。
winthegame 2006-02-21
  • 打赏
  • 举报
回复
Sorry, 下午发完贴就直接出去办事去了,晚上又看电视,现在才有空来看看。

看了楼上诸位的答案,我感觉还是没发现思路......

wangk(倒之): 使用SetUnhandledExceptionFilter 和 UnhandledExceptionFilter 处理,我之前在工程中用过,当时用于致命错误的捕捉,它替代系统的弹出的致命对话框条,记录崩溃现场的日志,虽然实用,但感觉并不适合此场合,LoadLibrary的错误 并不会导致 此类错误发生,这里难道要手动抛出错误?

idAnts(Coil & Nova Since 1985) :使用延迟调用DLL动态库首要条件就是此动态库为一个隐式加载的动态库,可偶的库是显式加载,且执行LoadLibrary即失败。此时如何使用上延迟调用技术?况且我们使用的动态库,有不少是第三方,即非本人编写的动态库,要那些库都实现延迟加载编译的话,并不现实啊......

flyelf(空谷清音[MVP]): GetLastError 返回的代码是126,既是 "找不到指定的模块" 错误,
LoadLibrary虽然知道加载的动态库 bbb.dll, 甚至连路径都清清楚楚,可是 bbb.dll 依赖的动态库 ccc.dll不存在,所以说显式一加载bbb.dll 就失败,那么如何让我得到是哪个 ccc.dll不存在呢?

实际上隐式加载非常常见,我们基于MFC编写的动态库都是隐式加载了MFC42, MFC71等的动态库,而实际加载这些动态库时如果没有相关隐式链接的那些动态库,loadLibrary就会出错, 此时如何
让我自己代码获得此类错误呢?

盼楼上兄弟继续关注,期待找到答案。
teli_eurydice 2006-02-21
  • 打赏
  • 举报
回复
关注这个问题
flyelf 2006-02-21
  • 打赏
  • 举报
回复
其实GetLastError已经告诉你原因,只不过是具体的现实需要自己去组织:首先LoadLibrary知道当前要载入哪个dll,其次,可以从系统变量中得到dll的载入路径,两者相加就是隐式连接时的系统提示
idAnts 2006-02-21
  • 打赏
  • 举报
回复
使用DelayLoad技术。MSDN里有篇文章,你找找看。给你个例子:

#pragma comment( lib, "DELAYIMP.LIB" )

#pragma comment(linker, "/DELAYLOAD:DelayLoadDLL.dll")
#pragma comment(linker, "/DELAY:nobind ")
#pragma comment(linker, "/DELAY:unload ")

#pragma comment( lib, "..\\DelayLoadDLL\\Release\\DelayLoadDLL.lib" )//这个是dll的库
extern void foo();/////这个是需要调用的函数

__try
{
foo();
__FUnloadDelayLoadedDLL("DelayLoadDLL.dll");
}
__except (DelayLoadDllExceptionFilter(GetExceptionInformation()))
{
}

LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep)
{
LONG lDisposition = EXCEPTION_EXECUTE_HANDLER;

PDelayLoadInfo pdli = PDelayLoadInfo(pep->ExceptionRecord
->ExceptionInformation[0]);

char sz[500] = { 0 };

switch (pep->ExceptionRecord->ExceptionCode)
{
case VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND):
wsprintf(sz, "Dll not found: %s", pdli->szDll);
break;

case VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND):
if (pdli->dlp.fImportByName)
{
wsprintf(sz, "Function %s was not found in %s",
pdli->dlp.szProcName, pdli->szDll);
}
else
{
wsprintf(sz, "Function ordinal %d was not found in %s",
pdli->dlp.dwOrdinal, pdli->szDll);
}
break;
default:
lDisposition = EXCEPTION_CONTINUE_SEARCH;
break;
}

if (lDisposition == EXCEPTION_EXECUTE_HANDLER)
{
MessageBox(NULL, sz, NULL, MB_OK);
}
return(lDisposition);
}
wangk 2006-02-21
  • 打赏
  • 举报
回复
http://www.vckbase.com/code/downcode.asp?id=2495
wangk 2006-02-21
  • 打赏
  • 举报
回复
请用顶层异常处理SetUnhandledExceptionFilter,可以获取错误。
在UnhandledExceptionFilter,系统会给你现场和详细的信息。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧