The below code gives the error Variable is undefined (500) when trying to concatenate the error.no in the echo:
'Raise an error to represent an issue with the main code
err.raise 999
dim error
set error = err
'Call another function that could also throw an error
SendMail "To=me","From=me","Subject=Failure in main code"
'Report both errors
wscript.echo "First problem was - Error code:" & error & vbcrlf & "Subsequent problem was - Error code:" & err
Is it possible to clone the err object?
In addition to Ekkehard.Horner, you can also create a custom error class with the same behaviour as the error object. Because the err object is global, you can load it inside the class without passing it to it in a method.
On error resume Next
a = 1 / 0
Set myErr = new ErrClone
On error goto 0
WScript.Echo myErr
' returns 11, the default property
WScript.Echo myErr.Number & vbTab & myErr.Description & vbTab & myErr.Source
' returns 11 Division by zero Microsoft VBScript runtime error
Class ErrClone
private description_, number_, source_
Public Sub Class_Initialize
description_ = Err.Description
number_ = Err.Number
source_ = Err.Source
End Sub
Public Property Get Description
Description = description_
End Property
Public Default Property Get Number
Number = number_
End Property
Public Property Get Source
Source = source_
End Property
End Class
To copy the properties of the global Err object to a new variable for later use (after the global Err was changed by new catastrophies. .Clear, or "On Error GoTo 0") you should use an array:
>> On Error Resume Next
>> a = 1 / 0
>> Dim aErr : aErr = Array(Err.Number, Err.Description, Err.Source)
>> On Error GoTo 0
>> WScript.Echo Join(aErr, "-")
>>
11-Division by zero-Microsoft VBScript runtime error
because you can't create an empty Err object in VBScript.
Related
I want to use VBScript to catch errors and log them (ie on error "log something") then resume the next line of the script.
For example,
On Error Resume Next
'Do Step 1
'Do Step 2
'Do Step 3
When an error occurs on step 1, I want it to log that error (or perform other custom functions with it) then resume at step 2. Is this possible? and how can I implement it?
EDIT: Can I do something like this?
On Error Resume myErrCatch
'Do step 1
'Do step 2
'Do step 3
myErrCatch:
'log error
Resume Next
VBScript has no notion of throwing or catching exceptions, but the runtime provides a global Err object that contains the results of the last operation performed. You have to explicitly check whether the Err.Number property is non-zero after each operation.
On Error Resume Next
DoStep1
If Err.Number <> 0 Then
WScript.Echo "Error in DoStep1: " & Err.Description
Err.Clear
End If
DoStep2
If Err.Number <> 0 Then
WScript.Echo "Error in DoStop2:" & Err.Description
Err.Clear
End If
'If you no longer want to continue following an error after that block's completed,
'call this.
On Error Goto 0
The "On Error Goto [label]" syntax is supported by Visual Basic and Visual Basic for Applications (VBA), but VBScript doesn't support this language feature so you have to use On Error Resume Next as described above.
Note that On Error Resume Next is not set globally. You can put your unsafe part of code eg into a function, which will interrupted immediately if error occurs, and call this function from sub containing precedent OERN statement.
ErrCatch()
Sub ErrCatch()
Dim Res, CurrentStep
On Error Resume Next
Res = UnSafeCode(20, CurrentStep)
MsgBox "ErrStep " & CurrentStep & vbCrLf & Err.Description
End Sub
Function UnSafeCode(Arg, ErrStep)
ErrStep = 1
UnSafeCode = 1 / (Arg - 10)
ErrStep = 2
UnSafeCode = 1 / (Arg - 20)
ErrStep = 3
UnSafeCode = 1 / (Arg - 30)
ErrStep = 0
End Function
You can regroup your steps functions calls in a facade function :
sub facade()
call step1()
call step2()
call step3()
call step4()
call step5()
end sub
Then, let your error handling be in an upper function that calls the facade :
sub main()
On error resume next
call facade()
If Err.Number <> 0 Then
' MsgBox or whatever. You may want to display or log your error there
msgbox Err.Description
Err.Clear
End If
On Error Goto 0
end sub
Now, let's suppose step3() raises an error. Since facade() doesn't handle errors (there is no On error resume next in facade()), the error will be returned to main() and step4() and step5() won't be executed.
Your error handling is now refactored in 1 code block
I'm exceptionally new to VBScript, so this may not be considered best practice or there may be a reason it shouldn't be done this that way I'm not yet aware of, but this is the solution I came up with to trim down the amount of error logging code in my main code block.
Dim oConn, connStr
Set oConn = Server.CreateObject("ADODB.Connection")
connStr = "Provider=SQLOLEDB;Server=XX;UID=XX;PWD=XX;Databse=XX"
ON ERROR RESUME NEXT
oConn.Open connStr
If err.Number <> 0 Then : showError() : End If
Sub ShowError()
'You could write the error details to the console...
errDetail = "<script>" & _
"console.log('Description: " & err.Description & "');" & _
"console.log('Error number: " & err.Number & "');" & _
"console.log('Error source: " & err.Source & "');" & _
"</script>"
Response.Write(errDetail)
'...you could display the error info directly in the page...
Response.Write("Error Description: " & err.Description)
Response.Write("Error Source: " & err.Source)
Response.Write("Error Number: " & err.Number)
'...or you could execute additional code when an error is thrown...
'Insert error handling code here
err.clear
End Sub
What #cid provided is a great answer. I took the liberty to extend it to next level by adding custom throw handler (like in javascript). Hope someone finds its useful.
option Explicit
Dim ErrorCodes
Set ErrorCodes = CreateObject("Scripting.Dictionary")
ErrorCodes.Add "100", "a should not be 1"
ErrorCodes.Add "110", "a should not be 2 either."
ErrorCodes.Add "120", "a should not be anything at all."
Sub throw(iNum)
Err.Clear
Dim key
key = CStr(iNum)
If ErrorCodes.Exists(key) Then
Err.Description = ErrorCodes(key)
Else
Err.Description = "Error description missing."
End If
Err.Source = "Dummy stage"
Err.Raise iNum 'raise a user-defined error
End Sub
Sub facade(a)
if a=1 then
throw 100
end if
if a = 2 then
throw 110
end if
throw 120
End Sub
Sub Main
on error resume next
facade(3)
if err.number <> 0 then
Wscript.Echo Err.Number, Err.Description
end if
on error goto 0
End Sub
Main
Following script runs successfully in excel but throws syntax error when executed through .vbs file or in winautomation. I'm new to vb, please help.
Sub Test()
sUser = "TheUserName"
sDN = "uid=" & sUser & ",o=users,dc=MyDomain,dc=it"
sRoot = "LDAP://MyLDAPServer/o=users,dc=MyDomain,dc=it"
Dim oDS: Set oDS = GetObject("LDAP:")
On Error GoTo AuthError
Dim oAuth: Set oAuth = oDS.OpenDSObject(sRoot, sDN, "ThePassword", &H200)
On Error GoTo 0
MsgBox "Login Successful"
Exit Sub
AuthError:
If Err.Number = -2147023570 Then
MsgBox "Wrong Username or password !!!"
End If
On Error GoTo 0
End Sub
From Handling Errors in VBScript.
There is little difference between the methods used in Visual Basic and those used with VBScript. The primary difference is that VBScript does not support the concept of error handling by continuing execution at a label. In other words, you cannot use On Error GoTo in VBScript. Instead, use On Error Resume Next and then check both Err.Number and the Count property of the Errors collection, as shown in the following example: (example not provided here - use link for example)
So you will require your own error handling code section.
On Error Resume Next
Dim oAuth: Set oAuth = oDS.OpenDSObject(sRoot, sDN, "ThePassword", &H200)
Select Case Err.Number
Case 0:
'ERROR_SUCCESS - do nothing
Case -2147023570
MsgBox Err.Number & ": " & Err.Description &Chr(10) & "Wrong Username or password !!!"
Err.Clear
Exit Sub
Case Else
'deal with other errors
MsgBox Err.Number & ": " & Err.Description
Err.Clear
Exit Sub
End Select
More on getting error information at Information.Err Method.
I am trying to create a high-quality ErrorHandler. I get run-time error 438:
Object doesn't support this property or method
Here's code:
Sub Function_asdf()
...
On Error GoTo ErrorHandler
...
ErrorHandler:
& vbNewLine & "Error" & Err.Number & Err.line & Err.Description
Like that, you're doing nothing. You're trying to start a chain of strings, but this starts with a join operator (&) which is not connecting to any "first" part, and even if it was it's neither assigned to a variable nor shown into a dialog box.
Start by showing that into a MsgBox :
MsgBox vbNewLine & "Error" & Err.Number & Err.line & Err.Description
or assigning it to a variable first:
Dim errMsg As String
errMsg = vbNewLine & "Error" & Err.Number & Err.line & Err.Description
and then printing it:
Debug.Print errMsg
or logging it into a cell
Range("A1") = errMsg
or in a MsgBox
MsgBox errMsg
... and don't forget to specify on which line you're raising the exception (here it's clear, but it's not always evident) cause it would be impossible for someone to debug without knowing in which point of your code the exception is thrown.
EDIT - I've finally run your code
So, I've run your code and the error is raised because the object Err (i.e. the exception thrown) does not have the property Line. It might have been deprecated, or just never existed.
If you wanted to return the line on which the error occurs, use the ERL property:
MsgBox vbNewLine & "Error" & Err.Number & Erl & Err.Description
Hi im looking for a formulla to show User's full name who is opening excel file.it should show that logged in user name. I tried some VBA script and got succesfull but there is one problem that when i run script that time only it Generate pop up windows saying your user name. it should show user name in cell as a date formulla a"=TODAY()". i have this script please anybody help me to show full user name in cell.
Sub GetUserFullName()
Dim MyOBJ As Object
On Error Resume Next
Set MyOBJ = GetObject("WinMgmts:").instancesOf("Win32_NetworkLoginProfile")
If Err.Number <> 0 Then
MsgBox "WMI has not been installed, code will be terminated...", vbExclamation, "Windows Management Instrumentation"
Exit Sub
End If
For Each objItem In MyOBJ
MyMsg = MyMsg & "Welcome To IT Dept : " & vbCrLf & vbCrLf & objItem.FullName
Next
MsgBox MyMsg, vbInformation, "Swapnil (System Admin)"
End Sub
UPD:
Function GetUserFullName() As String
Dim MyOBJ As Object
Dim res As String
On Error Resume Next
Set MyOBJ = GetObject("WinMgmts:").instancesOf("Win32_NetworkLoginProfile")
If Err.Number <> 0 Then
GetUserFullName = "error"
Exit Function
End If
For Each objItem In MyOBJ
res = res & objItem.FullName
Next
GetUserFullName = res
End Function
you can use it in any cell like formula: =GetUserFullName()
I'm trying to update document properties and create new entries if they don't exist
However
this type of thing does not work
Set objDocProps = DSO.GetDocumentProperties(sfilename:=FileName)
With objDocProps
If .CustomProperties("ABC") Is Nothing Then
'create it here
and if I put an error handler in there
it barfs as either being locked or having lost connection
errhandler:
Select Case Err.Number
Case -2147220987 ' missing custom property
Debug.Print "missing custom property"
With objDocProps
.CustomProperties("ABC").Value = "banana!"
Could you use the CustomDocumentProperties collection for the appropriate Excel workbook instead? You could then just iterate through the collection and edit the property if you find it. If it is not present you could then create the property
There appear to be issues when trying to access CustomProperties by name.
The solution I have implemented is to iterate the CustomPropery collection to determine the index of the item (if it exists), then use this to set the value (or add a new one if it does not)
Pass in: your custom properties object, the entry you wish to populate and the value you wish to populate it with
Sub UpsertEntry(objCustomProps, entryname, entryvalue)
'update the custom property with value supplied
On Error Resume Next
Dim icount
Dim iindex
For icount = 1 To objCustomProps.Count
If objCustomProps.Item(icount).name = entryname Then
iindex = icount
Exit For
Else
iindex = 0
End If
Next
If iindex = 0 Then 'no custom property found
objCustomProps.Add entryname, entryvalue
Wscript.Echo " Adding [" & entryname & ":" & entryvalue & "]"
Else
objCustomProps.Item(iindex).Value = entryvalue
Wscript.Echo " Changing [" & entryname & ":" & entryvalue & "]"
End If
On Error GoTo 0
End Sub