9

willを使用Err.Raise 65536すると、Err.Number実際には 65536 ではなく 5 の値になるのはなぜですか?

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`
4

4 に答える 4

11

MSDN ドキュメントから:

番号

必須。エラーの性質を識別する倍長整数。Visual Basic エラーの範囲は 0 ~ 65535です。0 ~ 512 の範囲はシステム エラー用に予約されています。ユーザー定義エラーには、513 ~ 65535 の範囲を使用できます。クラス モジュールで Number プロパティを独自のエラー コードに設定する場合は、エラー コード番号を vbObjectError 定数に追加します。たとえば、エラー番号 513 を生成するには、vbObjectError + 513 を Number プロパティに割り当てます。

したがって、65535 より大きい値を送信できても、65535 より大きい値はエラー 5 になります。

于 2012-09-21T17:14:41.027 に答える
10

「マイクロソフトがそう言った」を超えるレベルがあります。発生するエラー番号は 32 ビット整数です。これは、コンポーネント間でエラーを渡すための COM 仕様の一部であるためです。コンポーネントのすべてのパブリック メソッドは、実際には戻り値として HRESULT を返す関数です。VB 関数がある場合、関数の戻り値を秘密裏に [out] パラメータにマップします。HRESULT 値は、値のヒープ全体で構成されるビットフィールドです。ただし、単純にするために、2 つの 16 ビット部分に分割できます。下位 16 ビットには実際のエラー番号が含まれており、0 から 65535 (符号なし 16 ビットの範囲) の間になります。上位 16 ビットには多くの規格があります。最も重要なのは 0x0000____ です。これを使用するすべての定数は "S_" (成功の略) で始まります。最も一般的に使用される 32 ビット値は S_OK (0x00000000) です。この値が返された場合、関数は成功しています。ほとんどの VB メソッド呼び出しは、この値を返します。ただし、最上位ビットが設定されている値は、エラーが発生したことを示します。16 進数では、これらは 0x8___ のような値です。エラーには多くのクラスがあります。VB がデフォルトで返すものは 0x800A です。ただし、COM 仕様では、公式に使用できるクラスは 0x8004 のみです。これは、VB では定数 vbObjectError として表されます。

実際、VB では、ActiveX DLL または EXE のパブリック メソッドでエラーが発生する場合は、vbObjectError 定数を使用することをお勧めしています。やるかやらないかは関係ありません。これは、呼び出し元のコードが受け取ったエラーが非常に大きく負であることを意味するだけなので、エラー番号と &H0000FFFF の AND をとって 16 ビット整数を取得する必要があります。興味深いことに、それはまた、あなたがしないことをお勧めしますおそらく、ActiveX コントロール メソッドに関連付けられている上位 16 ビットが 0x800A000 であるためです。さらに興味深いことに、VB 自体は、デフォルトでエラー番号を上げると、すべてのエラー番号と 0x800A0000 の AND をとります。同様に、エラー番号が 0x800A____ のようなものであるかどうかを検出します。そうであれば、とにかく上位 1​​6 ビットを削除するので、エラー番号自体を処理するだけです。私の職場には、多くの VB コンポーネントがあります。私たちの標準は、エラー コードと vbObjectError の論理和をとらないことです。これにより、後で呼び出しコードでそれをマスクする必要がなくなります。

たとえば、COMPONENT1.CLASS1 と COMPONENT2.CLASS2 があるとします。CLASS1.Method1 は CLASS2.Method1 を呼び出します。CLASS2 でエラーが発生した場合は、CLASS1.Method1 で処理する必要があります。Microsoft の指示に従って、次のように記述します。

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 Function

COMPONENT2.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 Function

COMPONENT2.CLASS2 Enum EErrComponent2 ecBlahBlahError End Enum

Function Method1()
...
    Err.Raise EErrComponent1
...
End Function

vbObjectError を使用していないときに問題が発生したことがある人はいないでしょうか。確かにそうではありません。

于 2012-09-22T15:39:01.593 に答える
9

エラー5は

Run-Time Error '5': Invalid Procedure Call or Argument”

ジャスティンの答えに加えて、これは理にかなっています。Raise 関数は、無効な引数であるため、65535 を超える整数で呼び出すと、エラー 5 をスローします。

いくつかのコードを表示していただけますか。もう少しお手伝いできますか?

于 2012-09-21T17:13:56.300 に答える
0

Numberは として指定されていますが、LongそのドキュメントでErr.Raiseは、値 0 ~ 65535 のみが有効であると記載されています。したがって、表示されているエラーは、実際には の制約に違反しているためですErr.Raise

なぜにしなかったのかIntegerは謎です(おそらく今後有効範囲が拡大された場合に備えて)。

于 2012-09-21T17:15:24.747 に答える