一种可能性是:你的VB IDE中的tools->option->ErrTrapping设置成了Break on All Errors,而你在dll里捕获了这个错误,这样在调试时错误就会抛出,而运行时没有。另外一种可能性是你的dll客户代码的输入参数没有覆盖到抛出错误的代码。有可能的话还是把代码贴出来吧另外,我认为用运行时错误机制优于错误返回值机制,它可以简化调用方代码、分离正常/异常的控制流,更明晰得体现出代码的责任
to sogno : 能说说 运行时错误机制 与 错误返回值机制 吗?
我的程序好了. 我把 dll 里的 On Err GoTo Handler 去掉,就好了
to Bluess(布鲁斯) : 在vb中使用错误返回机制,首先就是要捕获所有可能发生的错误,并一一转换为相应的返回值举个简单的例子吧 有3个函数func1、func2、func3,其中func1调用func2,func2调用func3,它们共同完成一项任务func3位于调用序列的最底层的,它捕获所有的运行时刻错误。但是由于它没有足够的信息来处理这些错误,就把错误转换为相应的返回值: Public Function func3() As Long On Error GoTo Err
Call DoSomeThing '这里可能会发生运行时刻错误
func3 = 0 '成功退出 Exit Function Err: Select Case Err.Number Case InsufficientMemory func3 = -1 '出错 Case WriteDiskError func3 = -2 '出错 Case LowPower func3 = -3 '又出错 End Select On Error GoTo 0 End Functionfunc2接受func3的返回值,并且能够处理其中一部分错误,剩下的错误它没有办法解决,就返回给它的调用方,另外它也无法处理所有它捕获到的运行时刻错误,也转换为返回值一并返回 Public Function func2() As Long Dim result As Long result = func3 If 0 = result Then On Error GoTo Err Call GoOnDoingTheRest '这里可能会发生运行时刻错误 func2 = 0 ElseIf -3 = result Then Call SwitchToUPS '不会出错 Else func2 = result End If Exit Function Err: func2 = -4 On Error GoTo 0 End Functionfunc1是调用序列中的最后一个,它要处理掉前面处理不了的错误,同样的,它也要捕获所有的运行时刻错误。它罩不住的时候,就丢给用户 Public Sub sub1() Dim result As Long result = func2 If 0 = result Then On Error GoTo Err CompleteTheMission '这里可能会发生运行时刻错误 ElseIf -2 = result Then BuyNewDisk "120G" '不会出错 ChangeDisk "120G" '不会出错 ElseIf -1 = result Then BuyMemory "512M" '不会出错 AppendMemory "512M" '不会出错 Else MsgBox "搞不定了,您老看着办吧" End If Exit Sub Err: On Error GoTo 0 MsgBox "搞不定了,您老看着办吧" End Sub对于计算机来说,这些代码是完美的,它指出了通向圆满完成任务的成功之路,可是对于需要维护这段程序的人来说,事情就不是那么美好了。首先,整齐的、具有正确缩进的if-else语句抹煞了正常控制流和异常控制流的区别,业务逻辑、出错处理都掺杂在一起。当然,对于这个简单的例子来说,以绝大大部分程序员的理解能力来说都不成问题,但如果流程再复杂一些,比如具有多种正常状态的返回值,还有需要捕获更多的错误等等,那时想要加入一个新的正常/异常分支就困难了
下面换成运行时错误机制来处理相同的问题: sub3(原来的func3)由于不知道如何处理遇到的错误,就干脆不处理,只做它的事 代码如下:'我是以前的func3 Public Sub sub3() On Error GoTo Err Call DoSomeThing '这里可能会发生运行时刻错误 End Subsub2(原来的func2)调用sub3,它知道停电了该怎么处理,其他的它不清楚,就原样送到调用方那边好了 代码如下:'我是以前的func2 Public Sub sub2() On Error GoTo Err
Call sub3 Call GoOnDoingTheRest '这里可能会发生运行时刻错误
Exit Sub Err: Dim errorNumber As Long errorNumber = Err.Number On Error GoTo 0 If errorNumber = LowPower Then SwitchToUPS '不会出错 Else Err.Raise errorNumber End If End Subsub1(原来的func1)代码:'我是以前的sub1 Public Sub sub1() On Error GoTo Err
Call sub2 CompleteTheMission '这里可能会发生运行时刻错误
Exit Sub Err: Dim errorNumber As Long errorNumber = Err.Number On Error GoTo 0 Select Case errorNumber Case InsufficientMemory BuyNewDisk "120G" '不会出错 ChangeDisk "120G" '不会出错 Case WriteDiskError BuyMemory "512M" '不会出错 AppendMemory "512M" '不会出错 Case Else MsgBox "搞不定了,您老看着办吧" End Select End Sub我们看到,上面的sub1、sub2、sub3的业务代码和错误处理逻辑是界限分明的,无论是业务流程发生了变化,还是需要处理新的错误,修改起来都不困难,也就降低了代码维护的成本。
public function a as string
a=err.description
end function你通过得到A的内容,就可以得到错误信息了,我就是这样处理的。
在vb中使用错误返回机制,首先就是要捕获所有可能发生的错误,并一一转换为相应的返回值举个简单的例子吧
有3个函数func1、func2、func3,其中func1调用func2,func2调用func3,它们共同完成一项任务func3位于调用序列的最底层的,它捕获所有的运行时刻错误。但是由于它没有足够的信息来处理这些错误,就把错误转换为相应的返回值:
Public Function func3() As Long
On Error GoTo Err
Call DoSomeThing '这里可能会发生运行时刻错误
func3 = 0 '成功退出
Exit Function
Err:
Select Case Err.Number
Case InsufficientMemory
func3 = -1 '出错
Case WriteDiskError
func3 = -2 '出错
Case LowPower
func3 = -3 '又出错
End Select
On Error GoTo 0
End Functionfunc2接受func3的返回值,并且能够处理其中一部分错误,剩下的错误它没有办法解决,就返回给它的调用方,另外它也无法处理所有它捕获到的运行时刻错误,也转换为返回值一并返回
Public Function func2() As Long
Dim result As Long
result = func3
If 0 = result Then
On Error GoTo Err
Call GoOnDoingTheRest '这里可能会发生运行时刻错误
func2 = 0
ElseIf -3 = result Then
Call SwitchToUPS '不会出错
Else
func2 = result
End If
Exit Function
Err:
func2 = -4
On Error GoTo 0
End Functionfunc1是调用序列中的最后一个,它要处理掉前面处理不了的错误,同样的,它也要捕获所有的运行时刻错误。它罩不住的时候,就丢给用户
Public Sub sub1()
Dim result As Long
result = func2
If 0 = result Then
On Error GoTo Err
CompleteTheMission '这里可能会发生运行时刻错误
ElseIf -2 = result Then
BuyNewDisk "120G" '不会出错
ChangeDisk "120G" '不会出错
ElseIf -1 = result Then
BuyMemory "512M" '不会出错
AppendMemory "512M" '不会出错
Else
MsgBox "搞不定了,您老看着办吧"
End If
Exit Sub
Err:
On Error GoTo 0
MsgBox "搞不定了,您老看着办吧"
End Sub对于计算机来说,这些代码是完美的,它指出了通向圆满完成任务的成功之路,可是对于需要维护这段程序的人来说,事情就不是那么美好了。首先,整齐的、具有正确缩进的if-else语句抹煞了正常控制流和异常控制流的区别,业务逻辑、出错处理都掺杂在一起。当然,对于这个简单的例子来说,以绝大大部分程序员的理解能力来说都不成问题,但如果流程再复杂一些,比如具有多种正常状态的返回值,还有需要捕获更多的错误等等,那时想要加入一个新的正常/异常分支就困难了
sub3(原来的func3)由于不知道如何处理遇到的错误,就干脆不处理,只做它的事
代码如下:'我是以前的func3
Public Sub sub3()
On Error GoTo Err
Call DoSomeThing '这里可能会发生运行时刻错误
End Subsub2(原来的func2)调用sub3,它知道停电了该怎么处理,其他的它不清楚,就原样送到调用方那边好了
代码如下:'我是以前的func2
Public Sub sub2()
On Error GoTo Err
Call sub3
Call GoOnDoingTheRest '这里可能会发生运行时刻错误
Exit Sub
Err:
Dim errorNumber As Long
errorNumber = Err.Number
On Error GoTo 0
If errorNumber = LowPower Then
SwitchToUPS '不会出错
Else
Err.Raise errorNumber
End If
End Subsub1(原来的func1)代码:'我是以前的sub1
Public Sub sub1()
On Error GoTo Err
Call sub2
CompleteTheMission '这里可能会发生运行时刻错误
Exit Sub
Err:
Dim errorNumber As Long
errorNumber = Err.Number
On Error GoTo 0
Select Case errorNumber
Case InsufficientMemory
BuyNewDisk "120G" '不会出错
ChangeDisk "120G" '不会出错
Case WriteDiskError
BuyMemory "512M" '不会出错
AppendMemory "512M" '不会出错
Case Else
MsgBox "搞不定了,您老看着办吧"
End Select
End Sub我们看到,上面的sub1、sub2、sub3的业务代码和错误处理逻辑是界限分明的,无论是业务流程发生了变化,还是需要处理新的错误,修改起来都不困难,也就降低了代码维护的成本。
1、在错误处理不完善的情况下是危险的——如果没有完全捕获运行时刻错误,应用程序会立即退出,这可能导致用户的工作成果的丢失。这对系统的设计和测试提出了更高的要求。但是另外一方面,采用返回值的方式来处理错误的系统如果也有错误处理不完善的情况,虽然系统不会意外中止,但是在系统出错之后,系统内部已经无法保持正常的状态,很可能就会发生预期之外的行为,造成数据的丢失,甚至是严重的安全漏洞,而用户却浑然不觉。2、与C++/java/.net系列语言的异常错误处理机制相比,vb的运行时刻错误处理机制过于简单了——它抛出的是错误号而不是异常对象,使得vb的异常无法类型化,失去了诸如编译时刻检查、只捕获特定类型异常/错误(从而进一步简化调用方异常处理代码)等等的好处。我觉得这可能由vb语言的特性决定的。vb不是一门真正的oo的语言,它既不支持实现继承,也不支持完全的接口继承,我想这是vb的设计人员没有采用对象化的异常处理机制的原因吧。