Private Sub Form_Load()
On Error GoTo Err
MDE.Conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\Database\Report.mdb;Persist Security Info=False"
Exit Sub
Err: MsgBox "Database Error: Failed To Connect!", vbOKOnly + vbCritical, "Error!"
End Sub
I coded this and it worked properly last night, and this morning I moved that folder to try whether it works or not. After I moved it, it shows an error.
runtime error (-2147024770). The specified module could not be found
I have no idea to solve this error. I have tried to see the doc and nothing helped me out.
Related
I have the following code in visual basic , which I am running through visual studio .
Module Module1
Sub Main()
On Error GoTo errorHandler
Dim oLapp As Object
Dim oItem As Object
oLapp = CreateObject("Outlook.application")
oItem = oLapp.createitem(0)
'
With oItem
.Subject = "A MAIL"
.To = "an_email_id#outlook.com"
.body = "2018 RUSSIA IS OURS"
.Send
End With
Console.Write("KROOOOOOOOSSSSSS")
Console.Read()
'Set oLapp = Nothing
'Set oItem = Nothing
errorhandler:
Console.Write("jkjk")
End Sub
End Module
This code is purported to send an email through outlook . However , I thought of doing this through command prompt and I got to know about "cscript" command which is used to run VB scripts in windows command prompt .
So , I put the following code in an notepad file and saved it with .vbs extension . Then when I tried calling this file using cscript , I got an error .
It said syntax error at line 7 , col23 .
That line turns out to be :
On Error goto Errhandler
As such I commented that line out and tried running again and got an error again in line 8 , stating "expected end of statement .
So , I thought cscript might still be supporting "set" and "let" and hence put set in line 8 and I got the same error again .
So , is there any difference in the compilation of visual basic code in both these places . What will be the equivalent code of the code presented here that can be run via cscript and perform the task of sending an email through outlook .
In VBScript I am running a program I expect is likely to be in the PATH or current directory of the script. However if it is not in those places and cannot be found the script stops with error "The system cannot find the file specified". The command is not crucial and I would like to continue even in that case. Is that possible?
As #Noodles pointed out in the comments you can use On Error Resume Next to have the interpreter hand over error handling to you/your code, and then "handle" the error by glossing over it:
Set sh = CreateObject("WScript.Shell")
...
On Error Resume Next
sh.Run "unimportant.exe", 0, True
On Error Goto 0
...
If you want to be a little more diligent and have the script fail if other errors occur add a routine to check the error number and quit after displaying an error message if it's neither 0 nor 0x80070002:
Set sh = CreateObject("WScript.Shell")
...
On Error Resume Next
sh.Run "unimportant.exe", 0, True
If Err.Number <> 0 And Err.Number <> &h80070002 Then
WScript.Echo Trim("[0x" & Hex(Err.Number) & "] " & Err.Description)
WScript.Quit 1
End If
On Error Goto 0
...
Be very careful when using On Error Resume Next, though. Use it sparingly, and disable it again (On Error Goto 0) as soon as possible. Contrary to popular belief the statement doesn't magically make errors go away. It just hands full responsibility for checking and handling errors over to you. Basically it's the VBScript term for "shut up, I know what I'm doing".
The below script will fail with an error, which I'm ok with. Right now, I'm trying to work out my On Error GoTo <label> syntax, and it is currently failing with the following error.
Line: 2
Char: 16
Error: Syntax Error
Code: 800A03EA
Source: Microsoft VBScript compilation error
Code below:
Sub ComCheck
On Error GoTo ErrorHandler
Dim fortis
Wscript.Echo("Creating COM object.")
Set fortis = CreateObject("TESTCOM.APPLICATION")
Wscript.Echo("Write Database name.")
Wscript.Echo(fortis.Databases[0].Name)
GoTo ScriptEnd
ErrorHandler:
Wscript.Echo("-------ERROR OCCURRED------")
Wscript.Echo("#" + Err.Number + "::" + Err.Description)
Err.Clear
ScriptEnd:
Wscript.Echo("Script complete.")
End Sub
ComCheck()
This is one of the differences between VB and VBScript: the latter doesn't support the GoTo <label> syntax. The only two possibilities in VBScript are:
On Error Resume Next
and
On Error Goto 0
You use the former to turn off VBScript's own error handling (and presumably handle errors yourself), and the latter to turn on VBScript's error handling (which stops all execution if an error is encountered).
I'm trying the following code:
Try ' DOESN'T WORK
Throw 2 ' How do I throw an exception?
Catch ex
'What do I do here?
End Try
but I'm getting the error Statement expected in the catch clause.
Does anyone know how I can catch/throw exceptions in VBScript using try/catch? (I am not looking for solutions with On Error Do X.)
Handling Errors
A sort of an "older style" of error handling is available to us in VBScript, that does make use of On Error Resume Next. First we enable that (often at the top of a file; but you may use it in place of the first Err.Clear below for their combined effect), then before running our possibly-error-generating code, clear any errors that have already occurred, run the possibly-error-generating code, and then explicitly check for errors:
On Error Resume Next
' ...
' Other Code Here (that may have raised an Error)
' ...
Err.Clear ' Clear any possible Error that previous code raised
Set myObj = CreateObject("SomeKindOfClassThatDoesNotExist")
If Err.Number <> 0 Then
WScript.Echo "Error: " & Err.Number
WScript.Echo "Error (Hex): " & Hex(Err.Number)
WScript.Echo "Source: " & Err.Source
WScript.Echo "Description: " & Err.Description
Err.Clear ' Clear the Error
End If
On Error Goto 0 ' Don't resume on Error
WScript.Echo "This text will always print."
Above, we're just printing out the error if it occurred. If the error was fatal to the script, you could replace the second Err.clear with WScript.Quit(Err.Number).
Also note the On Error Goto 0 which turns off resuming execution at the next statement when an error occurs.
If you want to test behavior for when the Set succeeds, go ahead and comment that line out, or create an object that will succeed, such as vbscript.regexp.
The On Error directive only affects the current running scope (current Sub or Function) and does not affect calling or called scopes.
Raising Errors
If you want to check some sort of state and then raise an error to be handled by code that calls your function, you would use Err.Raise. Err.Raise takes up to five arguments, Number, Source, Description, HelpFile, and HelpContext. Using help files and contexts is beyond the scope of this text. Number is an error number you choose, Source is the name of your application/class/object/property that is raising the error, and Description is a short description of the error that occurred.
If MyValue <> 42 Then
Err.Raise(42, "HitchhikerMatrix", "There is no spoon!")
End If
You could then handle the raised error as discussed above.
Change Log
Edit #1:
Added an Err.Clear before the possibly error causing line to clear any previous errors that may have been ignored.
Edit #2:
Clarified.
Edit #3:
Added comments in code block. Clarified that there was expected to be more code between On Error Resume Next and Err.Clear. Fixed some grammar to be less awkward. Added info on Err.Raise. Formatting.
VBScript doesn't have Try/Catch. (VBScript language reference. If it had Try, it would be listed in the Statements section.)
On Error Resume Next is the only error handling in VBScript. Sorry. If you want try/catch, JScript is an option. It's supported everywhere that VBScript is and has the same capabilities.
Try Catch exists via workaround in VBScript:
http://web.archive.org/web/20140221063207/http://my.opera.com/Lee_Harvey/blog/2007/04/21/try-catch-finally-in-vbscript-sure
Class CFunc1
Private Sub Class_Initialize
WScript.Echo "Starting"
Dim i : i = 65535 ^ 65535
MsgBox "Should not see this"
End Sub
Private Sub CatchErr
If Err.Number = 0 Then Exit Sub
Select Case Err.Number
Case 6 WScript.Echo "Overflow handled!"
Case Else WScript.Echo "Unhandled error " & Err.Number & " occurred."
End Select
Err.Clear
End Sub
Private Sub Class_Terminate
CatchErr
WScript.Echo "Exiting"
End Sub
End Class
Dim Func1 : Set Func1 = New CFunc1 : Set Func1 = Nothing
Sometimes, especially when you work with VB, you can miss obvious solutions. Like I was doing last 2 days.
the code, which generates error needs to be moved to a separate function. And in the beginning of the function you write On Error Resume Next. This is how an error can be "swallowed", without swallowing any other errors. Dividing code into small separate functions also improves readability, refactoring & makes it easier to add some new functionality.
I'm using an error handler on my main calling procedure and letting the other procedures just roll up to that error handler.
Should I be clearing the error each time? Or should I Exit Sub instead of letting the error handler continue on the End Sub?
I'm asking because I've read that I may catch the first error, and then the other errors won't be handled.
Sorry if this is less than clear. Not really sure what I'm saying.
Thanks!!
Edit: Something like this. Is this necessary?
Public Sub SubA()
On Error Goto ProcError
' other code
MsgBox FuncA()
ProcExit:
Exit Sub
ProcError:
MsgBox Err.Description
Resume ProcExit
End Sub
OP: Should I be clearing the error each time? Or should I Exit Sub instead of letting the error handler continue on the End Sub?
What do you mean by clearing the Error?
Usually, the procedure is written in this manner
public sub myProcedure()
on error goto e:
'statements that could raise error
exit sub
e:
Log err.Number, err.Description, "error occurred in myProcedure"
end sub
OR
You could choose not to add the error handler. In which case, the error will be propagated to the caller (or the procedure where it is handled).
Please post the sample code of what you are trying to achieve & your expectation.
EDIT: Here is what the code posted by you means
Public Sub SubA()
On Error Goto ProcError
' other code
MsgBox FuncA()
exit sub 'put exit sub otherwise it will execute the line below, even if no error
ProcExit:
'this statement will get executed after the error msgbox is shown
msgbox "Reached ProcExit"
Exit Sub
ProcError:
MsgBox Err.Description 'catch the error and show the msgbox
'error is cleared the point it reaches ProcError
'Resume ProcExit acts as goto, to execute any statements after the error is handled
Resume ProcExit
End Sub
With your particular example, you do not need to clear the errors out because your pattern is based on catching errors. Though it does not hurt:
ProcExit:
Exit Sub
ProcError:
MsgBox Err.Description
Err.Clear
Resume ProcExit
Now, if you had a pattern where you checking for errors instead of catching them, then yes, you'd have to clear it. Here is small example:
On Error Resume Next
Dim o as Object
Set o = myCollection(someKey)
if Err.Number <> 0 then
... respond to error
Err.Clear
I hope this helps.
The Err object is cleared whenever you exit a Sub as expected (e.g., no error occurs). In your example, the Resume ProcExit statement is unnecessary. The following two subs behave the same way:
Public Sub SubA()
On Error Goto ProcError
MsgBox FuncA()
ProcExit:
Exit Sub
ProcError:
MsgBox Err.Description
Resume ProcExit
End Sub
Public Sub SubA()
On Error Goto ProcError
MsgBox FuncA()
Exit Sub
ProcError:
MsgBox Err.Description
End Sub
You don't have to use the Exit Sub statement to clear the Err object. Simply falling out of the sub when you hit End Sub has the same affect.
If you want errors from "the other procedures" to "roll up" (a better word is propagate) to the error handler on your main calling procedure, they shouldn't contain error handlers at all. For instance, suppose Main calls SubA, and SubA calls FuncA. An error occurs in FuncA. If you handle the error in FuncA by simply displaying a message box, like you do in your example, the code is going to continue executing in SubA, but will be in an unstable state because something went wrong in FuncA and SubA does not know about it.
One option is to refrain from putting error handlers in SubA and FuncA. When an error happens in FuncA, it gets raised to SubA, which in turn raises it to Main where it is then properly handled.
An even better option is to trap the errors, log them, then re-raise them. Then when the error finally gets to your Main Sub with the error handler, you'll have more information to work with.