Объявление API:
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, _
ByVal HWnd As Long, _
ByVal msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
приведет к аварийному завершению работы Excel, если ему будет предоставлен несуществующий указатель на функцию для параметра lpPrevWndFunc
.
Аналогично,
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As LongPtr, _
ByRef Source As LongPtr, _
ByVal Length As Long)
не счастлив, когда Destination
или Source
не существует.
Я думаю, что эти ошибки являются нарушениями доступа к памяти. Я предполагаю, что Windows говорит вызывающей стороне, что она делает что-то, что она не может 1 - возможно, она отправляет сообщение в Excel, и для этого нет обработчика? MSDN имеет это , чтобы сказать об этом:
Системные ошибки при обращении к библиотекам динамической компоновки Windows (DLL) или
Ресурсы кода Macintosh не вызывают исключений и не могут быть перехвачены
с перехватом ошибок Visual Basic. При вызове функций DLL вы
следует проверять каждое возвращаемое значение на успех или неудачу (согласно
спецификации API), а в случае сбоя проверьте
значение в свойстве объекта Err LastDLLError. LastDLLError всегда
возвращает ноль на Macintosh.
(выделение мое)
Но в этих случаях у меня нет значений для проверки на ошибки, я просто получаю сбой.
1: При условии, что он улавливает ошибку, которая может возникнуть не всегда, если, скажем, перезапись памяти действительна, но не определена. Но, конечно, запись в ограниченную память или вызов фальшивых указателей должны быть уловлены до того, как они будут выполнены, верно?
Меня больше всего интересует:
Что является причиной этого сбоя (как , как он срабатывает , так и , что именно за механизмом стоит - как Excel знает, что он должен аварийно завершать работу?). По какому каналу сообщений передаются эти ошибки, и можно ли перехватить их с помощью кода VBA?
Может ли сбой быть проактивным (т.е. санация входов и т. Д.) Или ретроактивным (обработка ошибок).
Я думаю (1), вероятно, пролит свет на (2) и наоборот
В любом случае, если кто-то знает, как обрабатывать подобные ошибки API без сбоев Excel, или как избежать их возникновения, или что-то, что могло бы быть потрясающим. On Error Resume Next
вроде не работает ...
Sub CrashExcel()
On Error Resume Next 'Lord preserve us
'Copy 300 bytes from one non existent memory pointer to another
RtlMoveMemory ByVal 100, ByVal 200, 300
On Error Goto 0
Debug.Assert Err.LastDllError = 0 'Yay no errors
End Sub
Мотивация
Есть две основные причины, по которым я спрашиваю об этом:
Разработка кода (процесс отладки и т. Д.) Усложняется, когда Excel вылетает каждый раз, когда я совершаю ошибку. Это не то, что можно решить, просто сделав это правильно сам (и предоставив другой интерфейс клиентскому коду, который использует мои существующие правильные реализации вызовов API), потому что я редко делаю это правильно с первого раза!
Я хотел бы создать надежный код, способный обрабатывать ошибки при вводе пользователем (например, недействительные указатели функций или места записи в память). В некоторой степени это может быть решено, например, путем абстрагирования указателей функций в вызываемые классы, но это не является общим решением для других типов ошибок dll (и все еще не имеет дело с 1).
В частности, я пытаюсь разработать дружественный интерфейс для переноса таймеров WinAPI . Для этого требуется, чтобы с ними были зарегистрированы функции обратного вызова, которые (учитывая ограничения VBA) должны быть представлены в виде Long
указателей на функции (сгенерированных с ключевым словом AddressOf
).
Обратные вызовы поступают из кода пользователя и могут быть недействительными. Весь смысл моей упаковки - улучшить стабильность вызовов API, и это одна область, которая нуждается в улучшении.
Проблема копирования памяти, вероятно, выходит за рамки этого вопроса, она связана с созданием генераторов в VBA, но я думаю, что там будут применяться те же методы обработки ошибок, и это упрощает пример.
Я также получаю ошибки и сбои от API таймера, генерирующего слишком много необработанных сообщений для Excel.Еще раз мне интересно, как Windows сообщает Excel «Время сбоя сейчас», почему я не могу перехватить эту инструкцию и устранить ошибку самостоятельно (т.е. уничтожить все сделанные мной таймеры и очистить очередь сообщений)?