首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >VB中自动化错误的处理

VB中自动化错误的处理
EN

Stack Overflow用户
提问于 2014-12-11 18:01:48
回答 2查看 1.5K关注 0票数 2

EDIT#1我正在开发一个VB6 EXE应用程序,目的是向输出一些特殊的图形。

下面的示例代码将中的给定图形绘制为虚线。

代码语言:javascript
运行
复制
' 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)
  • 不正确的客户端数据(例如,将太大的Point_Array传递给New_Path.SetEntirePath)
  • 某些服务器功能不可用(例如当AI的当前层被锁定时)
  • 意外服务器行为

EDIT#2

不幸的是,由于这样的错误是由服务器应用程序(在我们的例子中是AI)引发的,它们的描述往往是不够的、糟糕的和误导的。错误情况可能取决于AI版本、安装的应用程序、系统资源等。单个问题可能导致不同的错误。将太大的Point_Array传递给New_Path.SetEntirePath (Windows SP3,Adobe CS3)的示例:

  • 对于32767及以上的数组大小,错误为-2147024809 (&H 80070057)“非法参数”。
  • 对于32000到32766的数组大小,错误为-2147212801 (&H 800421ff)“无法在路径中插入更多段。8191是最大的”。

EDIT#2结束

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

代码语言:javascript
运行
复制
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

正如您所看到的,错误编号和错误描述可以很容易地访问。但是,我也需要知道是什么调用导致了错误。这对于包含对自动化接口的许多调用的大型复杂过程非常有用。所以,我需要知道:

  1. 发生了什么错误?
  2. 是什么电话引起的?
  3. 在什么客户端发生了这种情况?

目标3可以被描述为here的技术所满足。因此,让我们关注目标1和目标2。目前,我可以看到两种检测失败调用的方法:

1)通过对描述进行硬编码,对自动化接口进行每次调用:

代码语言:javascript
运行
复制
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)通过设计一个调用任何自动接口调用的函数,将所有调用放在一起:

代码语言:javascript
运行
复制
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

薄弱环节:

  • 目标1不满意,因为CallByName总是提出自动化错误440
  • 需要拆分像PathItems.Add这样的表达式
  • 对于某些类型的自动化接口调用,处理速度大幅下降(高达3x)

强项

  • 简洁易读的代码,不重复错误语句

还有处理自动化错误的其他方法吗?

,对于2)的弱点#1有解决办法吗?

给出的代码可以改进吗?

任何想法都是值得赞赏的!提前感谢!

塞尔日

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-13 01:00:17

想一想为什么您可能想知道错误是从哪里引发的。原因之一是为了简单的调试目的。另一个更重要的原因是,当错误发生时,您希望做一些特定的事情来处理特定的错误。

正确的调试解决方案实际上取决于您要解决的问题。如果这是一个临时的bug搜索,并且您正在交互地工作,那么简单的Debug.Print语句可能就是您所需要的。您的解决方案#1是好的,如果您只有几个例程,您想要粒状错误标识,而且您可以容忍消息框弹出。然而,就像你说的,这是一种乏味和容易出错的做法,所以把它变成样板或某种“标准实践”是个坏主意。

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

例如,您可能有一个执行如下操作的例程:

代码语言:javascript
运行
复制
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

你基本上把你的大程序中的任何一行一行的错误处理都拉到更小的、重点更突出的例程中,然后调用它们。你可以免费“追踪”你的错误。(如果您有某种系统的跟踪系统,比如我在这里描述的那个-- https://stackoverflow.com/a/3792280/58845 --它非常适合。)

事实上,取决于您的需要,您可能最终会得到一个完整的类,只是为了“包装”您正在使用的库类的方法。当库由于任何原因有一个不方便的接口时,这类事情实际上是相当常见的。

我不会做的是你的解决方案2,这基本上是扭曲你的整个程序,只是为了找出哪里发生错误。我保证“通用”Invoke以后会给你带来麻烦。你最好做这样的事:

代码语言:javascript
运行
复制
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

我可能不会为了调试的目的而费心使用包装类。同样,任何包装器(如果您使用的话)的目的都是解决库接口的一些问题。但是包装器也使调试更容易。

票数 2
EN

Stack Overflow用户

发布于 2014-12-11 18:19:27

可以在VB6调试器中运行它。如果编译时没有优化(优化后不会识别代码),也可以从WinDbg或WER获得堆栈跟踪(使用GFlags设置它)。HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug是存储设置的地方。

还可以在调试器中启动。

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

下载并安装Windows调试工具

http://msdn.microsoft.com/en-us/windows/hardware/hh852363

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

在C:\中创建一个名为符号的文件夹

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

代码语言:javascript
运行
复制
srv*C:\symbols*http://msdl.microsoft.com/download/symbols

然后

代码语言:javascript
运行
复制
windbg -o -g -G c:\windows\system32\cmd.exe /k batfile.bat

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

输入lm列出加载模块,x *!*列出符号,bp符号名设置断点

da显示在该地址找到的ascii数据。 dda显示指针的值 kv 10显示最后10个堆栈帧 lm列表模块 *列出所有模块中的所有函数 P阶 !系统信息机

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27429431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档