Вопрос по runtime, callstack, vb6 – Можно ли программно получить стек вызовов в VB6?

13

Когда в функции возникает ошибка, я хотел бы знать последовательность событий, которые к ней приводят, особенно когда эта функция вызывается из дюжины разных мест. Есть ли способ получить стек вызовов в VB6, или мне нужно сделать это сложным путем (например, записи в журнале каждой функции и обработчика ошибок и т. Д.)?

Ваш Ответ

5   ответов
11

Вы должны сделать это трудным путем, но это еще не всеthat тяжело ... Серьезно, после того как вы написали шаблон один раз, он быстро копирует / вставляет / модифицирует, чтобы сопоставить имя функции в операторе Err.Raise с фактическим именем функции.

Private Function DoSomething(ByVal Arg as String)

    On Error GoTo Handler

    Dim ThisVar as String
    Dim ThatVar as Long

    ' Code here to implement DoSomething...

    Exit Function

Handler:
    Err.Raise Err.Number, , "MiscFunctions.DoSomething: " & Err.Description

End Function

Когда у вас есть вложенные вызовы, это раскручивается, когда каждая подпрограмма достигает своего обработчика и добавляет свое имя в описание ошибки. В функции верхнего уровня вы получаете «стек вызовов» показывает список вызванных подпрограмм, номер ошибки и описание ошибки, которая фактически произошла. Это не идеально, потому что вы не получаете номера строк, но я обнаружил, что они вам обычно не нужны, чтобы найти путь к проблеме. (И если вам действительно нужны номера строк, вы можете поместить их в функцию и ссылаться на них в операторе Err.Raise, используя переменную Erl. Без номеров строк это просто возвращает 0.)

Также обратите внимание, что внутри самой функции вы можете выдавать свои собственные ошибки со значениями интересных переменных в сообщении, например, так:

Err.Raise PCLOADLETTER_ERRNUM, , "PC Load Letter error on Printer """ & PrinterName & """"

(Подсветка синтаксиса выглядит превью в превью ... Интересно, как она будет выглядеть после публикации?)

проголосовал за письмо загрузки ПК
1

Как говорили другие люди (много лет назад, я вижу ... но так много людей все еще используют VB6! :)), я думаю, что программным способом невозможно получить стек вызовов, если вы не используете какой-либо сторонний инструмент ,

Но если вам нужно сделать это для целей отладки, вы можете рассмотреть возможность добавления к вызываемой подпрограмме необязательной входной строковой переменной, где бы вы указали имя вызывающей стороны.

Sub MyRoutine
    (...)  ' Your code here
    call DoSomething (Var1, Var2, Var3, "MyRoutine")
    '                                       ^
    '     Present routine's name -----------+

    (...)  ' Your code here

End Sub


Public DoSomething (DoVar1, DoVar2, DoVar3, Optional Caller as string = "[unknown]")
    Debug.Print " DoSomething Routine Called. Caller = " & Caller

    ... ' (your code here)

End Sub

Может быть, не так элегантно, но у меня это сработало.

С Уважением, Макс - Италия

Кто-нибудь когда-нибудь говорил, что VB6 элегантен?
3

Трудный, ручной способ - в значительной степени единственный путь. Если вы проверитеэтот вопрос, кто-то предложил инструмент под названием MZTools, который сделает большую часть тяжелой работы за вас.

Я использую MZTools в течение многих лет, и я согласен, что это отличный инструмент. Однако я искал альтернативу «трассировке стека бедняков». Я не думал, что он был, но подумал, что не мешало бы спросить здесь. raven
0

Compuware (или это был Numega в то время) DevStudio для Visual Basic 6 использовал для этого. Способ заключался в добавлении инструментария к каждому вызову, который вызывал очень маленький фрагмент кода, добавляемый в стек кода. При любой ошибке он сбрасывал этот стек вызовов, а затем делал такие вещи, как почта или отправка на веб-сервер всей отладочной информации. Добавление и удаление инструментов было потенциально смертельной операцией (особенно тогда, когда мы использовали VSS в качестве нашего источника контроля), но если это работало, это работало хорошо.

КакДаррел указалВы можете добавить что-то очень простое, используя MZTools и настроив шаблон. Это очень много работает и, вероятно, более эффективно, чем вознаграждение, но если вам очень трудно отследить ошибки, это может помочь).

9

Я уверен, что вы должны сделать это трудным путем. На моей предыдущей работе у нас был очень элегантный процесс обработки ошибок для VB6 с компонентами DCOM. Тем не менее, это был очень избыточный код, который должен был быть добавлен к каждому методу, настолько, что у нас были собственные инструменты, чтобы вставить все это для вас.

Я не могу дать слишком много информации о его реализации (и потому, что я забыл большую часть этого, и есть шанс, что они могут считать это коммерческой тайной). Одна вещь, которая действительно выделяется, это то, что имя метода не может быть получено во время выполнения, поэтому оно было добавлено как строковая переменная (некоторые разработчики копировали-вставляли вместо использования инструмента, и это приводило к ошибочным стекам. ..).

НТН

Это единственный способ, которым я знаю, чтобы сделать это. Как предлагается ниже, MZTools может помочь. В вашем шаблоне для обработчика ошибок, если вы собираетесь распространять ошибку, добавьте вашу текущую функцию / подпрограмму к источнику err.source.
Я убежден, что нет способа сделать то, что я просил, поэтому я приму этот ответ. raven

Похожие вопросы