4

很长一段时间以来,当我有一个错误处理程序时,我会让它报告错误被抛出的项目、模块和过程。我总是通过简单地通过常量存储它们的名称来实现这一点。我知道在一个类中,您可以使用 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

4 回答 4

2

这里有几个问题。

您可以通过调用 App.Name 来获取项目名称 您无法获取您所在的方法的名称。我建议使用MZ Tools的自动化过程模板,它会自动输入您需要的所有常量,您的头痛将结束.

最后一部分可能必须知道调用 ActiveX DLL 的 EXE(或 lib)的名称。要解决这个问题,请尝试以下操作:

'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
于 2009-06-26T20:15:40.823 回答
2

对于项目名称,我能想到的唯一方法是故意在 Sub Main() 中的某处抛出错误,并在错误处理代码中,将生成的 Err.Source 保存到全局变量 g_sProjectName 中。否则,我似乎记得有一个名为 TLBINF32.DLL 的免费 3rd 方 DLL 进行 COM 反射 - 但这对于您想要做的事情来说似乎太过分了,无论如何公共和私有之间可能存在差异类。最后,您可以使用二进制编辑器在您的 EXE 中搜索项目名称字符串,然后尝试从该位置读取该字符串。虽然令人沮丧的是每个项目和代码模块的名称都嵌入在 EXE 中,但似乎没有可预测的方式来执行此操作,因此不建议这样做。

于 2009-06-26T20:35:51.937 回答
1

不幸的是,您需要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

微软包括这些评论:

  • 所有打开的模块都包含在 Modules 集合中,无论它们是未编译的、已编译的、处于中断模式还是包含正在运行的代码。
  • 要确定单个 Module 对象是代表标准模块还是类模块,请检查 Module 对象的 Type 属性。
  • Modules 集合属于 Microsoft Access 应用程序对象。
  • Modules 集合中的各个 Module 对象从零开始索引。

到目前为止,我还没有找到任何关于引用当前项目或程序的内容。但这应该为您指明正确的方向。

于 2009-06-26T18:48:41.653 回答
0

我建议你看看CodeSMART for VB6,这个 VB6 插件有一个可定制的 错误处理方案管理器,它的宏可以将模块名称、方法名称等字符串插入到你的错误处理代码中,只需一个上下文菜单选择。

还有一些其他非常好的功能 - 在文件中查找搜索,它优于我在 ReSharper 之前看到的任何东西,一个 Tab Order 设计器等等。

在我以前的雇主,我们使用这个工具很多年了,从 2005 年的版本开始。一旦你习惯了它,没有它真的很难做到。

于 2009-07-02T04:41:16.253 回答