为什么当我使用Err.Raise 65536时,Err.Number的实际值是5而不是65536?
根据Raise的定义:Sub Raise(Number As Long, [Source], [Description], [HelpFile], [HelpContext])。传递的参数是Long,Err.Number也是Long。
那么为什么我不能使用大于65535的值呢?
Private Sub Command1_Click()
Dim a As Long
On Error GoTo ErrCatch
For a = 0 To 99999
Err.Raise a
DoEvents
Next a
Exit Sub
ErrCatch:
' this is where Err.Number is evaluated
Resume Next
End Sub`发布于 2012-09-22 01:14:41
从MSDN documentation:
编号
必填项。标识错误性质的长整型。Visual Basic错误的范围是0-65535;0-512的范围是为系统错误保留的;用户定义的错误的范围是513-65535。在类模块中将Number属性设置为您自己的错误代码时,需要将错误代码编号添加到vbObjectError常量中。例如,若要生成错误号513,请将vbObjectError + 513指定给number属性。
因此,即使您可以提交一个大于65535的值,但任何大于65535的值都将变成错误5。
发布于 2012-09-22 23:39:02
除了“微软这么说”之外,还有更深一层的东西。您引发的错误号是一个32位整数,因为这是用于在组件之间传递错误的COM规范的一部分。组件的所有公共方法实际上都是返回HRESULT作为返回值的函数;如果您有一个VB函数,它会秘密地将函数的返回值映射到out参数。HRESULT值是一个由整个值堆组成的位域;但为了简单起见,您可以将其分为两个16位部分。较低的16位包含实际错误号,恰好介于0和65535之间-无符号16位范围。对于高16位,有许多标准。最重要的是0x0000____。所有使用此参数的常量都以"S_“开头(表示成功)。最常用的32位值是S_OK (0x00000000)。如果返回此值,则函数已成功。大多数VB方法调用都会返回这个值。但是,设置了顶部位的任何值都表示存在错误。在十六进制中,这些值看起来像0x8___。有许多类别的错误。VB默认返回的是0x800A。然而,COM规范只为您提供了一个可以正式使用的类,0x8004 -它在VB中表示为常量vbObjectError。
事实上,VB建议您在ActiveX DLL或EXE中的公共方法上引发错误时使用vbObjectError常量。不管你做不做,都没有区别。这只意味着调用代码接收到的错误非常大且为负,因此您必须将错误号与&H0000FFFF进行and运算才能恢复16位整数。有趣的是,它还建议您不要对ActiveX控制方法执行此操作,这可能是因为与ActiveX控制方法相关的高16位是0x800A000。更有趣的是,默认情况下,当您引发错误号时,VB本身会将所有错误号与0x800A0000进行AND运算。同样,它会检测错误号是否像0x800A____一样-如果是,它会为您删除高16位,因此您只需处理错误号本身。在我的工作场所,我们有很多VB组件。我们的标准是与vbObjectError不对错误代码进行OR运算。这就省去了我们随后不得不在调用代码中屏蔽它的麻烦。
例如,如果您有COMPONENT1.CLASS1和COMPONENT2.CLASS2。CLASS1.Method1调用CLASS2.Method1。如果我在CLASS2中引发错误,那么我必须在CLASS1.Method1中处理它。按照微软的指示,我会这样写:
COMPONENT1.CLASS1
Function Method1()
On Error GoTo ErrorHandler
...
ErrorHandler:
If (Err.Number And vbObjectError) = vbObjectError Then
Select Case Err.Number And (Not vbObjectError)
Case Component2.EErrComponent2.ecBlahBlahError
... handle ...
End Select
End If
End FunctionCOMPONENT2.CLASS2
Enum EErrComponent2
ecBlahBlahError = 513 ' Minimum error code
End Enum
Function Method1()
...
Err.Raise EErrComponent1 Or vbObjectError
...
End Function对多个组件重复此操作,这个模板会让人有点厌烦,而且似乎没有给我们带来任何实际的回报。
我们可能会这样做:
COMPONENT1.CLASS1
Function Method1()
On Error GoTo ErrorHandler
...
ErrorHandler:
Select Case Err.Number
Case Component2.EErrComponent2.ecBlahBlahError
... handle ...
End Select
End FunctionCOMPONENT2.CLASS2枚举EErrComponent2 ecBlahBlahError End枚举
Function Method1()
...
Err.Raise EErrComponent1
...
End Function我想知道是否有人在不使用vbObjectError时遇到过问题。我们当然没有。
发布于 2012-09-22 01:13:56
错误5是
Run-Time Error '5': Invalid Procedure Call or Argument”加上贾斯汀的回答,这将是有意义的。当使用大于65535的整数调用Raise函数时,它会抛出错误5,因为它是一个无效参数。
你能展示一些代码吗?我可以帮你做得更好一些。
https://stackoverflow.com/questions/12535054
复制相似问题