一般而言,隐式加载如果加载出错的话,系统都会给予提示。例如 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,也许是一大段代码,总之,烦请指教。
---------------------------
aaa.exe - 无法找到 DLL
--------------------------
无法找到动态链接库 ccc.dll 于指定的路径 C:\WINNT\system32;C:\WINNT\system;C:\WINNT; 上。
---------------------------
确定
---------------------------而如果aaa.Exe显式加载了bbb.dll呢?那么,LoadLibrary 就会失败,使用GetLastError,得到错误代码126--找不到指定的模块,却无法获得如上的加载失败原因。这就让人一时摸不着头脑了....我的问题就是:如何在显式加载失败时,使之类似隐式加载一般,报告出加载失败的具体原因?解决此问题也许只是一个API,也许是一大段代码,总之,烦请指教。
在UnhandledExceptionFilter,系统会给你现场和详细的信息。
#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);
}
LoadLibrary虽然知道加载的动态库 bbb.dll, 甚至连路径都清清楚楚,可是 bbb.dll 依赖的动态库 ccc.dll不存在,所以说显式一加载bbb.dll 就失败,那么如何让我得到是哪个 ccc.dll不存在呢?实际上隐式加载非常常见,我们基于MFC编写的动态库都是隐式加载了MFC42, MFC71等的动态库,而实际加载这些动态库时如果没有相关隐式链接的那些动态库,loadLibrary就会出错, 此时如何
让我自己代码获得此类错误呢?盼楼上兄弟继续关注,期待找到答案。
1.判断该DLL是否存在
2.读取Dll的隐式加载需要的文件(PE格式分析)
3.SearchPath在当前文件夹和系统文件夹查找Dll的隐式加载需要的文件是否存在。
汗,如果真的需要象2一般,"读取dll的隐式加载需要的文件"的话,那么恐怕还要考虑递归---因为如果此dll隐式加载需要的dll可能也隐式加载了一些dll, 更何况如果将任意文件改名为那个需要的文件,你的方法也不适用--查找文件是能够找到的,而LoadLibrary仍然会报错,而且如果以上两点交给系统帮你做--既是不采取显式加载而是隐式加载,系统均能准确的将错误结论得出,所以说仍然没有找到思路呢......
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 映像。请再检测一遍您的安装盘。
---------------------------
确定
---------------------------可诊断性,两下相较,一目了然。
2.如果3用LoadLibrary判断呢?,如果任意文件改名为那个需要的文件还是能知道不能加载成功。
之前忙事,再加之再想其他方法,故而没有回答你,你的方法不能说行不通,但是用这种“交通基本靠走,娱乐基本靠手”的方法未免过于繁琐,等这段东西出来,那么倒之版的Depands 也出来了,其实只是需要获知系统信息而已,恐怕还有其他方法,我再想想了......,如果有新的想法,请提示。
我原来以为是因为采用隐式加载dll时会将所有这个dll与之相关的dll一起加入导出表,但是看来似乎不是(使用Depends看)
好像没有什么好的方法,你总不能让咱村前的小土路跑宝马之流的车子吧。交通不靠走是不成啦。只能请MS修路了……