Как узнать, в каком модуле выполняется мой код?

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

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

Option Compare Binary
Option Explicit
Option Base 0
Option Private Module

Private Const m_strModuleName_c As String = "MyModule"

Private Sub Example()
    Const strProcedureName_c As String = "Example"
    On Error GoTo Err_Hnd
Exit_Proc:
    On Error Resume Next
    Exit Sub
Err_Hnd:
    ErrorHandler.FormattedErrorMessage strProcedureName_c, m_strModuleName_c, _
        Err.Description, Err.Source, Err.Number, Erl
    Resume Exit_Proc
End Sub

Кто-нибудь знает способы для кода, чтобы сказать, где он находится? Если вы можете убедительно показать, что это невозможно, это тоже ответ:)

Редактировать:
Я также знаю, что имя проекта в Err.Source. Я надеялся получить его без исключения для других целей. Если вы прекрасно знаете, если нет, мы можем определить это как выходящий за рамки вопроса.
Я также знаю, как получить строку с ошибкой, но эта информация, конечно, только несколько полезна, не зная Module.Procedure.

4 ответа

Решение

Что касается имени проекта, я могу думать только об этом, преднамеренно выбрасывая ошибку где-нибудь в Sub Main(), а в коде обработки ошибок сохраняйте полученный Err.Source в глобальную переменную g_sProjectName. В противном случае, мне кажется, что я помню, что была бесплатная сторонняя DLL-библиотека TLBINF32.DLL, которая отражала COM - но это, кажется, слишком для того, что вы хотите сделать, и в любом случае, вероятно, есть разница между публичной и приватной классы. И, наконец, вы можете использовать бинарный редактор для поиска строки имени проекта в вашем EXE, а затем попытаться прочитать строку с позиции. Хотя разочарование вызывает то, что имена каждого проекта и модуля кода встроены в EXE-файл, кажется, что не существует предсказуемого способа сделать это, поэтому это НЕ рекомендуется.

Здесь есть несколько вопросов.

Вы можете получить имя проекта, вызвав App.Name. Вы не можете получить имя метода, в котором вы находитесь. Я рекомендую использовать шаблоны автоматизированных процедур из MZ Tools, которые автоматически вставят все необходимые вам константы, и ваша головная боль пройдет,

Последний кусок, возможно, должен знать имя EXE (или lib), который вызвал вашу ActiveX DLL. Чтобы понять это, попробуйте следующее:

'API Declarations'
Private Declare Function GetModuleFileName Lib _
    "kernel32" Alias "GetModuleFileNameA" (ByVal _
    hModule As Long, ByVal lpFileName As String, _
    ByVal nSize As Long) As Long

Private Function WhosYourDaddy() As String
    Dim AppPath As String
    Const MAX_PATH = 260

    On Error Resume Next

    'allocate space for the string'
    AppPath = Space$(MAX_PATH)

    If GetModuleFileName(0, AppPath, Len(AppPath)) Then
        'Remove NULLs from the result'
        AppPath = Left$(AppPath, InStr(AppPath, vbNullChar) - 1)
        WhosYourDaddy = AppPath
    Else
        WhosYourDaddy = "Not Found"
    End If
End Function

К сожалению, вам нужно иметь индивидуальный On Error GoTo X утверждения для отдельных модулей и процедур. Проект всегда хранится в Err.Source, Обработка ошибок VBA не так уж велика в этой области - в конце концов, насколько хорошо имя проекта является источником ошибки, в отличие от процедуры / модуля.

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

Если вы используете Access 2007 (не уверен насчет других приложений / версий Office), попробуйте следующий фрагмент кода, извлеченный из справочной документации:

Sub PrintOpenModuleNames()
    Dim i As Integer
    Dim modOpenModules As Modules

    Set modOpenModules = Application.Modules

    For i = 0 To modOpenModules.Count - 1

        Debug.Print modOpenModules(i).Name

    Next
End Sub

И Microsoft включает эти замечания:

  • Все открытые модули включены в коллекцию модулей, независимо от того, являются ли они некомпилированными, скомпилированы, находятся в режиме прерывания или содержат код, который выполняется.
  • Чтобы определить, представляет ли отдельный объект Module стандартный модуль или модуль класса, проверьте свойство Type объекта Module.
  • Коллекция модулей принадлежит объекту приложения Microsoft Access.
  • Отдельные объекты модуля в коллекции модулей индексируются, начиная с нуля.

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

Я предлагаю вам взглянуть на CodeSMART для VB6. Это дополнение для VB6 имеет настраиваемый диспетчер схем обработки ошибок, с макросами, которые вставляют строки для имени модуля, имени метода и т. Д. В код обработки ошибок с помощью одного выбора контекстного меню.

Имеет и другие очень приятные функции - поиск в файлах, который превосходит все, что я видел до ReSharper, дизайнера Tab Order и многое другое.

У моего предыдущего работодателя мы использовали этот инструмент много лет, начиная с версии 2005 года. Как только вы к этому привыкнете, без этого действительно трудно обойтись.

Другие вопросы по тегам