我的应用程序严重依赖插件。
在启动时,它会扫描目录中的DLL并逐个加载它们,寻找实现某个导出函数的目录。但是 - 如果有人要将不同类型的文件重命名为* .dll并将其放在目录中,则该文件也将由LoadLibrary()
加载。 LoadLibrary()
不喜欢这样,并产生错误[对话框]。
有没有办法可以简单地忽略无效/不兼容的.dll
文件(在通话之前检测它们或让LoadLibrary()
返回NULL
而不是投掷适合的文件)?
答案 0 :(得分:2)
您需要为流程设置错误模式。在启动时一劳永逸地做到这一点:
UINT oldMode = SetErrorMode(0);
SetErrorMode(oldMode | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
在您设置了过程错误模式后,当LoadLibrary
失败时,不会显示任何对话框,LoadLibrary
将返回NULL
。
最佳做法是所有应用程序在启动时使用参数SEM_FAILCRITICALERRORS调用流程范围的SetErrorMode函数。这是为了防止错误模式对话框挂起应用程序。
我还建议添加SEM_NOOPENFILEERRORBOX
,原因我认为应该是显而易见的。
答案 1 :(得分:1)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx
说明
要在DLL加载期间启用或禁用加载程序显示的错误消息,请使用SetErrorMode函数。
完成后不要忘记恢复错误模式。
如果你想自己这样做,你可以用原始方式解析PE头来识别坏DLL文件的明显情况,但是如果没有完整的PE加载器,确实无法确定DLL是否有效和可加载这需要大量的工作,并已内置到操作系统中。
答案 2 :(得分:1)
在djgandy和Remy Lebeau的评论中反馈后更新了答案。现在一个完整的 功能,在入口处更好地保留错误模式:
// This function will load the DLL named by pszPath if it is a valid library.
// If the function succeeds, it will return a valid HMODULE for the DLL. This
// handle should be passed to FreeLibrary when it is no longer needed.
// If the function fails, it will return NULL and no annoying dialog boxes will
// be displayed. It is therefore up to the caller to notify the user about what
// happened or take any other appropriate action. The reason for failure can
// be obtained from GetLastError(). Common problems:
// ERROR_BAD_EXE_FORMAT - Bad DLL (tested function with text file)
// ERROR_MOD_NOT_FOUND - Missing DLL (tested with file that did not exist)
//
// Module-loading functions can return several other errors, look at winerror.h
// list starting at ERROR_INVALID_MODULETYPE
//
// Obviously, since it's just a wrapper around LoadLibrary this function is not
// safe to call from DllMain.
//
// NB: GetErrorMode() is only available on Vista / Server 2003 or later.
HMODULE LoadLibraryIfValid(LPCTSTR pszPath)
{
HMODULE hModule = NULL;
UINT prevErrorMode = GetErrorMode();
SetErrorMode(prevErrorMode | SEM_FAILCRITICALERRORS);
hModule = LoadLibrary(pszPath);
SetErrorMode(prevErrorMode);
return hModule;
}
如果定位到Windows 7 / Server 2008 R2或更高版本,则为Get / SetThreadErrorMode() 功能可用,但可能不值得,甚至是一个很好的选择 (在下面的评论中讨论)
如果有人关心把时间花在它上面(我确定不要),那就是 对于kernel32和,可以使用GetModuleHandle轻松编写此函数 GetProcAddress与早期版本的Windows兼容 为支持它的平台提供全局/每线程错误模式选项 (真的没有意义,因为它只会在一次通话期间发生变化)。
这是我生命中最大的评论与代码比率。