Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.188.10.246] |
|
Сообщ.
#1
,
|
|
|
Я делаю вывод уведомлений об ошибках примерно так:
error_code = GetLastError(); result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error_code, 0, buff1, _countof(buff1), 0) if (result) { wnsprintfW(buff2, _countof(buff2), L"%Ошибка: %d - %s", error_code, buffer_text_error); } else { wnsprintfW(buff2, _countof(buff2), L"Ошибка: %d", error_code); } Столкнулся с тем что для некоторых ошибок FormatMessage возвращает 0 и не трогает буфер. Например, работая с WinHttp-функциями при недоступности запрашиваемого сайта получаю ошибку 12002. В WinInet.h она описана - ERROR_INTERNET_TIMEOUT. Но в FormatMessage её нет. Т.е. я пользователю могу сказать только «произошла ошибка 12002», а что это за ошибка – пользователю самому придётся искать. А как бы найти в системе человеческие описания подобных кодов ошибок? Есть варианты? Встроить в свою программу весь текст списков ошибок из WinInet.h и прочих заголовков - не хотелось бы… |
Сообщ.
#2
,
|
|
|
Цитата f2065 @ Столкнулся с тем что для некоторых ошибок FormatMessage возвращает 0 и не трогает буфер. f2065, в этом случае попробуй получить описание ошибки из конкретного модуля. Например: result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error_code, 0, buff1, _countof(buff1), 0) if (result) { wnsprintfW(buff2, _countof(buff2), L"%Ошибка: %d - %s", error_code, buffer_text_error); } else { HMODULE hDll = ::LoadLibraryEx(_T("netmsg.dll"),NULL,DONT_RESOLVE_DLL_REFERENCES); if(hDll) { result = ::FormatMessage ( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, ... ... ); ::FreeLibrary(hDll); } } |
Сообщ.
#3
,
|
|
|
Да, направление правильное.
Впрочем ситуация оказалась сложнее, нашёл в микрософте схожий пример… Суть в том что оказывается есть пересекающиеся диапазоны ошибок, надо помнить откуда ошибка была получена и использовать правильную DLL. В случае если ошибки жду только от WinHttp - получается так HMODULE hModuleExtra = 0; DWORD dwFormatFlags = FORMAT_MESSAGE_IGNORE_INSERTS; if (error_code >= WINHTTP_ERROR_BASE && error_code <= WINHTTP_ERROR_LAST) { hModuleExtra = LoadLibraryExW(L"WinHTTP.dll", NULL, LOAD_LIBRARY_AS_DATAFILE); if (hModuleExtra) { dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; } } if (!hModuleExtra) { dwFormatFlags |= FORMAT_MESSAGE_FROM_SYSTEM; } if (FormatMessageW(dwFormatFlags, hModuleExtra, error_code, 0, buffer_text_error, _countof(buffer_text_error), 0)) { wnsprintfW(tmp_pos, tmp_size, L"Error: %d - %s", error_code, buffer_text_error); } else { wnsprintfW(tmp_pos, tmp_size, L"Error: %d", error_code); } if (hModuleExtra) { FreeLibrary(hModuleExtra); } Даже вот с WinInet и WinHTTP - им выделен один и тот же диапазон (WINHTTP_ERROR_BASE == INTERNET_ERROR_BASE), часть кодов ошибок у них по сути совпадают, часть уникальные. Т.е. если у меня программа работает и с WinInet и с WinHTTP - то единую процедуру обработки ошибок сделать нельзя, ибо диапазон одинаковый а DLL с текстами ошибок у них надо разные грузить… Теперь вопрос такой - если у меня программа например работает с WinHTTP, и WinHTTP.dll статически прилинкована, то можно ли как-то избежать лишнего LoadLibrary ? Ведь DLL эта уже и так находится в адресном пространстве программы… А лишний LoadLibrary может ведь подхватить совсем не то что надо (если например в интервале между запуском программы и обработкой ошибки в %path% появится какая-то другая DLL с этим же именем). |
Сообщ.
#4
,
|
|
|
Цитата f2065 @ Теперь вопрос такой - если у меня программа например работает с WinHTTP, и WinHTTP.dll статически прилинкована, то можно ли как-то избежать лишнего LoadLibrary ? Ведь DLL эта уже и так находится в адресном пространстве программы… Лишний LoadLibrary ни к каким проблемам не приведёт. Просто вернёт handle на загруженную уже библиотеку и всё. Надо только не забыть использовать FreeLibrary. --- Попробуй использовать "GetModuleHandle". Но я так не делал. --- Можно сделать объект (c++), вызывать FreeLibrary из деструктора, и тогда потенциальные проблемы с высвобождением ресурса вообще исчезнут. |