Vb6 VB中自动化错误的处理

Vb6 VB中自动化错误的处理,vb6,automation,ui-automation,Vb6,Automation,Ui Automation,编辑#1 我正在开发一个VB6 EXE应用程序,用于向Adobe Illustrator输出一些特殊图形 下面的示例代码将Adobe Illustrator中的给定图形绘制为虚线多段线 ' Proconditions: ' ai_Doc As Illustrator.Document is an open AI document ' Point_Array represented as "array of array (0 to 1)" contains point coordinates '

编辑#1 我正在开发一个VB6 EXE应用程序,用于向Adobe Illustrator输出一些特殊图形

下面的示例代码将Adobe Illustrator中的给定图形绘制为虚线多段线

' Proconditions:
' ai_Doc As Illustrator.Document is an open AI document
' Point_Array represented as "array of array (0 to 1)" contains point coordinates
'
Private Sub Draw_AI_Path0(ByRef Point_Array As Variant)
Dim New_Path As Illustrator.PathItem
    Set New_Path = ai_Doc.PathItems.Add
    New_Path.SetEntirePath Point_Array
    New_Path.Stroked = True
    New_Path.StrokeDashes = Array(2, 1)
End Sub
但是,此简单代码可能会引发各种运行时自动化错误,这些错误由以下原因引起:

  • 客户端代码不正确(例如,将数组以外的值分配给
    New_Path.StrokeDashes
  • 客户端数据不正确(例如,将太大的
    点数组
    传递到
    新路径。SetEntirePath
  • 某些服务器功能不可用(例如,当AI的当前层被锁定时)
  • 意外的服务器行为
编辑#2

不幸的是,由于这些错误是由服务器应用程序(在我们的例子中是AI)引起的,所以它们的描述通常是不充分的、糟糕的和误导性的。错误情况可能取决于AI版本、安装的应用程序、系统资源等。单个问题可能导致不同的错误。将太大的
点数组
传递到
新路径.SetEntirePath
的示例(Windows XP SP3,Adobe Illustrator CS3):

  • 对于32767及以上的数组大小,错误为-2147024809(&H80070057)“非法参数”
  • 对于32000到32766的数组大小,错误为-2147212801(&H800421FF)“无法在路径中插入更多段。最大值为8191”
编辑结束#2

传统的错误处理可用于防止客户端崩溃,并显示错误详细信息,如下所示:

Private Sub Draw_AI_Path1(ByRef Point_Array As Variant)
Dim New_Path As Illustrator.PathItem
On Error GoTo PROCESS_ERROR
    Set New_Path = ai_Doc.PathItems.Add
    New_Path.SetEntirePath Point_Array
    New_Path.Stroked = True
    New_Path.StrokeDashes = Array(2, 1)
    Exit Sub
PROCESS_ERROR:
    MsgBox "Failed somewhere in Draw_AI_Path1 (" & Format(Err.Number) & ")" _
        & vbCrLf & Err.Description
End Sub
如您所见,可以轻松访问错误号和错误描述。但是,我还需要知道是什么调用导致了错误。这对于包含许多自动化接口调用的大型复杂过程非常有用。因此,我需要知道:

  • 发生了什么错误
  • 是什么电话引起的
  • 它发生在哪个客户端函数中
  • 目标#3可通过所述技术得到满足。那么,让我们关注目标1和2。目前,我可以看到两种检测失败呼叫的方法:

    1) 要通过硬编码描述“仪表化”对自动化接口的每次调用:

    Private Sub Draw_AI_Path2(ByRef Point_Array As Variant)
    Dim New_Path As Illustrator.PathItem
    Dim Proc As String
    On Error GoTo PROCESS_ERROR
        Proc = "PathItems.Add"
        Set New_Path = ai_Doc.PathItems.Add
        Proc = "SetEntirePath"
        New_Path.SetEntirePath Point_Array
        Proc = "Stroked"
        New_Path.Stroked = True
        Proc = "StrokeDashes"
        New_Path.StrokeDashes = Array(2, 1)
        Exit Sub
    PROCESS_ERROR:
        MsgBox "Failed " & Proc & " in Draw_AI_Path2 (" & Format(Err.Number) & ")" _
            & vbCrLf & Err.Description
    End Sub
    
    弱点:

    • 代码变大,可读性变差
    • 由于复制粘贴,可以指定不正确的原因
    优点

    • 两个目标都得到了满足
    • 最小处理速度影响
    2) 通过设计调用任何自动化接口调用的函数,将所有调用“仪器化”:

    Private Function Invoke( _
        ByRef Obj As Object, ByVal Proc As String, ByVal CallType As VbCallType, _
        ByVal Needs_Object_Return As Boolean, Optional ByRef Arg As Variant) _
        As Variant
    On Error GoTo PROCESS_ERROR
        If (Needs_Object_Return) Then
            If (Not IsMissing(Arg)) Then
                Set Invoke = CallByName(Obj, Proc, CallType, Arg)
            Else
                Set Invoke = CallByName(Obj, Proc, CallType)
            End If
        Else
            If (Not IsMissing(Arg)) Then
                Invoke = CallByName(Obj, Proc, CallType, Arg)
            Else
                Invoke = CallByName(Obj, Proc, CallType)
            End If
        End If
        Exit Function
    PROCESS_ERROR:
        MsgBox "Failed " & Proc & " in Draw_AI_Path3 (" & Format(Err.Number) & ")" _
            & vbCrLf & Err.Description
        If (Needs_Object_Return) Then
            Set Invoke = Nothing
        Else
            Invoke = Empty
        End If
    End Function
    
    
    Private Sub Draw_AI_Path3(ByRef Point_Array As Variant)
    Dim Path_Items As Illustrator.PathItems
    Dim New_Path As Illustrator.PathItem
        Set Path_Items = Invoke(ai_Doc, "PathItems", VbGet, True)
        Set New_Path = Invoke(Path_Items, "Add", VbMethod, True)
        Call Invoke(New_Path, "SetEntirePath", VbMethod, False, Point_Array)
        Call Invoke(New_Path, "Stroked", VbSet, False, True)
        Call Invoke(New_Path, "StrokeDashes", VbSet, False, Array(2, 1))
    End Sub
    
    弱点:

    • 由于自动化错误440总是由
      CallByName
    • 需要拆分表达式,如
      PathItems。添加
    • 某些类型的自动化接口调用的处理速度显著下降(高达3倍)
    优点

    • 简洁易读的代码,没有重复的错误语句
    是否有其他方法处理自动化错误?

    是否有解决弱点的方法#1换2)?

    给定的代码可以改进吗?

    任何想法都很感激!提前谢谢


    Serge将在VB6调试器中运行它。如果编译时未进行优化(优化后您将无法识别代码),您还可以从WinDbg或WER获取堆栈跟踪(使用GFlags进行设置)。HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug是存储设置的位置

    也可以在调试器中启动

    windbg或ntsd(ntsd是一个控制台程序,可能已安装)。这两个都来自Windows调试工具

    下载并安装Windows调试工具

    安装Windows SDK,但只需选择调试工具

    在C中创建名为Symbols的文件夹:\

    启动Windbg。文件菜单-符号文件路径并输入

    srv*C:\symbols*http://msdl.microsoft.com/download/symbols
    
    然后

    您可以按F12停止它,kb将显示调用堆栈(g继续程序)。如果出现错误,它也会停止并显示错误

    键入lm以列出加载的模块,x*!*列出符号和bp symbolname以设置断点

    da显示在该地址找到的ascii数据

    dda显示指针的值

    kv 10显示最后10个堆栈帧

    lm列表模块

    x*!*列出所有模块中的所有功能

    p步

    !!sysinfo机器ID

    如果在VB6中编程,则此环境变量link=/pdb:none将符号存储在dll中,而不是单独的文件中。确保编译程序时没有优化,并勾选“创建符号调试信息”框。两者都位于项目属性的“编译”选项卡上


    此外,CoClassSyms(microsoft.com/msj/0399/hood/hood0399.aspx)还可以从类型库中生成符号。

    想想原因,您可能想知道从何处引发错误。一个原因是出于简单的调试目的。另一个更重要的原因是,您想做一些特定的事情来处理发生的特定错误

    调试的正确解决方案实际上取决于您试图解决的问题。简单的
    Debug.Print
    语句可能是您所需要的全部,如果这是一个临时的bug查找,并且您正在交互工作。如果您只需要对一些例程进行粒度错误识别,并且您可以容忍弹出消息框,那么您的解决方案#1就可以了。然而,正如你所说,它有点乏味,而且容易出错,所以把它变成样板文件或某种“标准实践”是个坏主意

    但这里真正的危险信号是您的声明,即您有“包含许多对自动化接口的调用的大型复杂过程”,另外还需要以细粒度的方式处理或至少跟踪错误。解决这个问题的办法就是把你庞大而复杂的过程分解成一组简单的过程

    比如说
    windbg -o -g -G c:\windows\system32\cmd.exe /k batfile.bat
    
    Sub SetEntirePath(New_Path As Illustrator.PathItem, ByRef Point_Array As Variant)
        On Error Goto EH
    
        New_Path.SetEntirePath Point_Array
    
        Exit Sub
    
    EH:
    
        'whatever you need to deal with "set entire path" errors
    End Sub
    
    Private Sub Draw_AI_Path4(ByRef Point_Array As Variant)
    
        ...
    
        path_wrapper.SetEntirePath Point_Array
        path_wrapper.Stroked = True
        path_wrapper.StrokeDashes = Array(2, 1)
    
        ...
    
    End Sub