VBA CVErr() and the Err.Raise() test
About HRESULT
Win uses a 32-bit HRESULT value system to standardize error handling mechanism.
HRESULT: as a signed integer a negative value indicates failure and other values indicate success.
31 26 15 0 +-+-+-+-+-+-+---+---+---+---+---+---+---+---+---+---+---+---+---+ |S R C N r| Facility | Code | +-+-+-+-+-+-+---+---+---+---+---+---+---+---+---+---+---+---+---+
S=0 success
S=1 failure
The R, C, N, and r bits are reserved in the HRESULT
Facility is a 11-bit field: for 2048 different sub-systems for error origin (ex. FACILITY_STORAGE=3, FACILITY_DISPATCH=2, FACILITY_WIN32=7)
Code is the unsigned 16-bit error code itself 0-65535.
Facility 0Ah is used by VBA to generate Legacy BASIC error codes (see below).
VBA vbObjectError = &H80040000. This is failure from FACILITY_ITF.
CVErr() makes HRESULT
The conversion function CVErr(Code):
- returns Variant of type Variant/Error (vbError=10) that stores a 32-bit HRESULT value
- Code is a Long value with valid range of 00000000-0000FFFF (16-bits). Any other value gives Run-time error 5, Invalid procedure call or argument.
CVErr(0) returns all zero Success HRESULT in the Variant, others generate "Automation error" S=1 failure with Facility=0A. Here is a memory dump:
CVErr(0) ---> 0A00-000000000000-0000000000000000-0000000000000000 64-bit Variant/Error (S=0 success) CVErr(1..65535) ---> 0A00-000000000000-xxxx0A8000000000-0000000000000000 64-bit Variant/Error (S=1 failure)
When converting Variant/Error to Long we get only the lower 16-bits:
31 15 0 +-------------------------------+---+---+---+---+---+---+---+---+ | | Code | Long +-------------------------------+---+---+---+---+---+---+---+---+ | CVErr(Code) | V 31 26 15 0 +-+-+-+-+-+-+---+---+---+---+---+---+---+---+---+---+---+---+---+ |S 0 0 0 0| 0A | Code | HRESULT in Variant/Error +-+-+-+-+-+-+---+---+---+---+---+---+---+---+---+---+---+---+---+ | CLng(Variant) | V 31 15 0 +-------------------------------+---+---+---+---+---+---+---+---+ | | Code | Long +-------------------------------+---+---+---+---+---+---+---+---+
Excel also uses some of the Variant/Error values. When a UDF function returns Variant/Error into a cell, f. ex. CVErr(2042), Excel will display it as #N/A
.
Constant Error number Cell error value xlErrDiv0 2007 #DIV/0! xlErrNA 2042 #N/A xlErrName 2029 #NAME? xlErrNull 2000 #NULL! xlErrNum 2036 #NUM! xlErrRef 2023 #REF! xlErrValue 2015 #VALUE!
The VBA Err()
function
Err()
is a Public function of Module Information. It returns an instance of ErrObject
, which is a Class of VBA:
VBE7.DLL Class ErrObject VBA +-----------------+ |__ .. | Number | |___ Class ErrObject | Description | |___ Module Information | Raise() | |__ .. |___ .. | Clear() | |___ Function Err() As ErrObject | ... | |__ .. +-----------------+
Err is a short-cut for Err(): Err.Raise(N) = Err().Raise(N)
Run-time errors or Err.Raise()
fills out values in the ErrObject
instance and VBA starts looking for an error handler along the call stack.
If Err is not cleared, only Number is updated when a subsequent Err.Raise()
is called. This can happen in error handlers or after On Error Resume Next
. Internal Run-time errors update all values in the ErrObject
.
The big Err.Raise()
test
This is an investigation to call Err.Raise(Number)
in a VBA Module and observing the result in the ErrObject
. Raise causes Run-time error that is trapped in the same procedure with On Error GoTo. The test code:
Sub errtrap() On Error GoTo label Err.Raise N ... Exit Sub label: check Err.Number... check Err.Description... ... Resume Next End Sub
Err.Raise(Number)
expects a 32-bit Long argument for Number. Err.Number
is also 32-bit Long value.
This is a flowchart what may happen internally:
Err.Raise(N) Err.Number Err.Description +----------+ +----------+ ? +----------+ | 00000000 | ---> | S00A0005 | ---> | 0xxxxxxx | +----------+ +----------+ | +----------+ +----------+ +----------+ | +----------+ | 0xxxxxxx | ---> | S00A0005 | ---> | S00A0000 | +----------+ +----------+ | +----------+ +----------+ +----------+ | SUCCESS | 0000xxxx | ---> | S00Axxxx | | +----------+ +----------+ | +----------+ +----------+ | ---> | S00Axxxx | ---> | 0000xxxx | | | +----------+ +----------+ +----------+ | +----------+ | ^ Standard BASIC error or | Sxxxxxxx | ----------- ----> | HRESULT | --- | "Application-defined or object-defined error" +----------+ +----------+ | |some ^ | +----------+ +----------+ | ---> | Sxxxxxxx | ---> | Sxxxxxxx | | +----------+ +----------+ Run-time "Automation error" + optional Description Other Automation Objects
Err.Raise()
in VBA code is raising an error: all Number values are converted to S=1 failure HRESULT codes. The run-time works with HRESULT internally and can also receive HRESULT success/failure codes from other Automation Objects. The HRESULT dispather then delivers codes to ErrObject with possible translations. S=0 success codes do not raise an error, execution continues with the next statement.
All these result were made using Err.Raise()
only and in VBA64. Certain results are probably specific to an actual Win- and Office version.
Raising S=0
Valid only in the range of 00000001-0000FFFF, similar to CVErr()
. All other values raise 5, "Invalid procedure call or argument":
Raise N -----------> Err.Number 00000000 5, Invalid procedure call or argument 00000001 - 0000FFFF Err.Number = N 00010000 - 07FFFFFF 5, Invalid procedure call or argument (sometimes 5, "Class not registered"?)
In the 0001-FFFF range many of them are Standard BASIC errors, like 3, "Return without GoSub".
Unused codes keep N and put "Application-defined or object-defined error" in Description.
I have not tested all above 65535..
Some of the Standard errors:
00000003 Return without GoSub 00000005 Invalid procedure call or argument 00000006 Overflow 00000007 Out of memory 00000009 Subscript out of range 0000000A This array is fixed or temporarily locked 0000000B Division by zero 0000000D Type mismatch 0000000E Out of string space 00000010 Expression too complex 00000011 Can't perform requested operation 00000012 User interrupt occurred 00000014 Resume without error 0000001C Out of stack space .... .... 000002E8 Search text not found 000002EA Replacements too long
Raising S=1
Generally, all negative S=1 failure HRESULT in VBA is "Automation error" with an optional error in Description. Most of HRESULT-s after Err.Raise()
comes back untranslated in Err.Number. Facility code matters etc.
Raise N ----> Err.Number Raise 8xxxxxxx ----> 8xxxxxxx "Automation error"
Several HRESULT-s are translated to Standard errors and multiple HRESULT-s raised by Automation Objects can be translated to the same Legacy Error code. F. ex.:
Raise 80020001 ----> 000001B6 Object doesn't support this property or method Raise 80020003 ----> 000001B6 Object doesn't support this property or method
This also means that getting an "Object doesn't support this property or method" in VBA we have no idea about the original Automation error.
Raising Facility 0Ah S=1 will be translated to Legacy VBA errors (therefore I think VBA works internally with HRESULT). F. ex.:
Raise 800A0000 ----> SUCCESS, NOTHING HAPPENS, executes next statement Raise 800A0001 ----> 1, "Application-defined or object-defined error" Raise 800A0002 ----> 2, "Application-defined or object-defined error" Raise 800A0003 ----> 3, "Return without GoSub" ... ... Raise 800AFFFF ----> 65535, "Application-defined or object-defined error"
An interesting test: Raise Sxxx0003 for all 2048 Facility where result is not merely "Automation error". A method to discover sub-systems and Facility codes:
80000003 Automation error One or more arguments are invalid 80010003 Automation error The caller is dispatching an intertask SendMessage call and cannot call out via PostMessage. 000001B6 Object doesn't support this property or method 0000004C Path not found 80040003 Automation error This implementation doesn't take advises 80070003 Automation error The system cannot find the path specified. 80080003 Automation error RPC communication failed with OLE service 80090003 Automation error Bad Key. 00000003 Return without GoSub 800B0003 Automation error The form specified for the subject is not one supported or known by the specified trust provider. 800C0003 Automation error No Internet session has been established. 800F0003 Automation error The syntax of the INF is invalid. 80100003 Automation error The supplied handle was invalid. 80190003 Automation error Unexpected redirection status code (3xx). 801F0003 Automation error Asynchronous requests are not valid for this operation. 80270003 Automation error The entity ID conflicts with an already registered id. 80280003 Automation error TPM 1.2: One or more parameter is bad. 802A0003 Automation error This method cannot be called during this type of callback. 80310003 Automation error The BIOS did not correctly communicate with the master boot record (MBR). Contact the computer manufacturer for BIOS upgrade instructions. 80320003 Automation error The filter does not exist. 80390003 Automation error Some BCD entries were not synchronized correctly with the firmware. 803B0003 Automation error The network's underlying layer was not found. 803D0003 Automation error The operation is not allowed due to the current state of the object. 80400003 Automation error One or more fields in the input packet are invalid. 80550003 Automation error The EAS policy being evaluated cannot be enforced by the system. 80630003 Automation error The required service cannot be started. 80650003 Automation error The attribute cannot be written. 80660003 Automation error HD Audio widget does not support the connection list parameter. 80670003 Automation error The StateRepository configuration is not valid. 80830003 Automation error The specified storage tier could not be found on the volume. Confirm that the storage tier name is valid. 80860003 Automation error The application requesting authentication tokens is either disabled or incorrectly configured. 80B00003 Automation error Could not connect to dbgsrv server from ARM architecture device. 80E70003 Automation error The specified resiliency type is not valid. 83750003 Automation error Missing required element. 83760003 Automation error Protocol extensions are not supported. 87AF0003 Automation error Access permission denied
No comments:
Post a Comment