文章目录
- vs2019 - LoadLibrary失败时的排查方法
- 概述
- 笔记
- 用GetLastError()看错误原因
- 隐式调用DLL接口看错误原因
- 总结
- END
vs2019 - LoadLibrary失败时的排查方法
概述
在做从内存载入DLL的实验,发现从内存载入DLL失败。
昨天还是成功的。昨天将工程归档了,清掉了临时文件。应该是少了啥依赖的东西。
用LoadLibrary显式载入,也失败。
去查msdn, WIN32API失败后,可以调用GetLastError() + FormatMessage()来显示失败信息。
这时显示的信息为确实为依赖的模块,具体哪个模块,还不清楚。
最后,直接隐式调用DLL接口,如果是缺哪个依赖的模块,直接有messagebox提示,一目了然。
笔记
用GetLastError()看错误原因
void ShowError(DWORD dwErrId, LPCTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
// WORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErrId,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
// strsafe.h
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dwErrId, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
void CLoaderDlg::test5() {
// typedef bool (APIENTRY* PFN_testOssl)();
HMODULE hDll = NULL;
PFN_testOssl pfn = NULL;
bool b_rc = false;
DWORD dwRc = 0;
do {
hDll = ::LoadLibraryA("DllForTest_x64Debug.dll");
if (NULL != hDll) {
pfn = (PFN_testOssl)::GetProcAddress(hDll, "testOssl");
if (NULL != pfn) {
b_rc = (*pfn)();
TRACE("%d = (*pfn)();\r\n", b_rc);
}
::FreeLibrary(hDll);
hDll = NULL;
}
else {
dwRc = GetLastError();
ShowError(dwRc, TEXT("LoadLibraryA"));
}
} while (false);
}
隐式调用DLL接口看错误原因
#pragma comment(lib, "DllForTest_x64Debug.lib")
extern "C" __declspec(dllimport) int APIENTRY FnAdd(int a, int b);
void CLoaderDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
FnAdd(1, 2);
}
原来是清理工程时,将依赖的glog日志dll整没了。
总结
如果是LoadLibrary失败,在工程中隐式调用DLL接口,让VS2019直接报错,这样最直接。