Hi,

I seem to have hit a bug in the error handling of VBScript. I ran into the
problem when trying to assign a user to a group, but the group doesnâ??t exist.
If Error Handling is not turned on, then the script crashes on the GetObject
statement as expected. However, I want to catch and log the error, and
continue on with the script. So, I used the normal code:

Set objGroup = GetObject(â??LDAP://cn=Sales,cn=Users,dc=fabrikam,dc=comâ??)
If Err.Number <> 0 Then
WScript.Echo â??Error â?? unable to bind to groupâ??
Else
WScript.Echo â??Group boundâ??
End If

In a main routine, this code behaves exactly as expected. However, if I put
this code into a Function, like so:

On Error Resume Next

If SetGroup() Then
WScript.Echo "Set Group Fine"
Else
WScript.Echo "Set Group Failed"
End If

Function SetGroup()

SetGroup = FALSE

set objGroup = GetObject("LDAP://cn=Sales,cn=Users,dc=fabrikam,dc=com")
WScript.Echo "Did we get to this line?"
If Err.Number <> 0 Then
WScript.Echo "Error"
SetGroup = FALSE
Else
WScript.Echo "Fine"
SetGroup = TRUE
End If

End Function ' Set Group

The Error Handling code no longer runs. Instead the Script drops out of the
function back to the main routine. The WScript.Echo directly after the
GetObject was added to verify that the problem was on the GetObject line, not
with the Error Handling afterwards. In this simplified sample program, the
program does not crash at the GetObject (though it will, as expected, without
the On Error Resume Next), instead it simply drops back to the main routine.
In this particular case, reporting â??Set Group Fineâ??.

The full script where I ran into this problem is much more complicated, and
the GetObject is in nested routines. The main routine calls a subroutine,
which calls another subroutine, which calls the function that contains the
GetObject statement. In this complex program, the script drops all the way
back to the main routine, not just out of the Function.

So far, I have not found any code examples for testing for the existence of
a Group the way I can test for the existence of a file. With the GetObjectâ??s
incorrect behavior when an error occurs Iâ??m not even sure how such a test can
be written and incorporated into real-world scripts, as such error handling
belongs in a Function or Subroutine. In most complex scripts you probably
wouldnâ??t even know the data you are looking for until you were into a
subroutine or function.

Any help would be greatly appreciated.

Jim Winner
Program Manager
The Catholic University of America

Re: Error handling bug on GetObject? by Tom

Tom
Tue Jul 11 19:59:10 CDT 2006

I believe the documentation covers this (but you have to read
carefully) and it's not a bug. The issue is the context of the error
handler. That is, the error handler you invoke at the top level of
your procedure is Not global to another routine called from it. You
need to invoke error handling specific to each function of subroutine
you might call from your main procedure.

Tom Lavedas
============
http://members.cox.net/tglbatch/wsh

James Winner wrote:
> Hi,
>
> I seem to have hit a bug in the error handling of VBScript. I ran into the
> problem when trying to assign a user to a group, but the group doesn't exist.
> If Error Handling is not turned on, then the script crashes on the GetObject
> statement as expected. However, I want to catch and log the error, and
> continue on with the script. So, I used the normal code:
>
> Set objGroup = GetObject("LDAP://cn=Sales,cn=Users,dc=fabrikam,dc=com")
> If Err.Number <> 0 Then
> WScript.Echo "Error - unable to bind to group"
> Else
> WScript.Echo "Group bound"
> End If
>
> In a main routine, this code behaves exactly as expected. However, if I put
> this code into a Function, like so:
>
> On Error Resume Next
>
> If SetGroup() Then
> WScript.Echo "Set Group Fine"
> Else
> WScript.Echo "Set Group Failed"
> End If
>
> Function SetGroup()
>
> SetGroup = FALSE
>
> set objGroup = GetObject("LDAP://cn=Sales,cn=Users,dc=fabrikam,dc=com")
> WScript.Echo "Did we get to this line?"
> If Err.Number <> 0 Then
> WScript.Echo "Error"
> SetGroup = FALSE
> Else
> WScript.Echo "Fine"
> SetGroup = TRUE
> End If
>
> End Function ' Set Group
>
> The Error Handling code no longer runs. Instead the Script drops out of the
> function back to the main routine. The WScript.Echo directly after the
> GetObject was added to verify that the problem was on the GetObject line, not
> with the Error Handling afterwards. In this simplified sample program, the
> program does not crash at the GetObject (though it will, as expected, without
> the On Error Resume Next), instead it simply drops back to the main routine.
> In this particular case, reporting "Set Group Fine".
>
> The full script where I ran into this problem is much more complicated, and
> the GetObject is in nested routines. The main routine calls a subroutine,
> which calls another subroutine, which calls the function that contains the
> GetObject statement. In this complex program, the script drops all the way
> back to the main routine, not just out of the Function.
>
> So far, I have not found any code examples for testing for the existence of
> a Group the way I can test for the existence of a file. With the GetObject's
> incorrect behavior when an error occurs I'm not even sure how such a test can
> be written and incorporated into real-world scripts, as such error handling
> belongs in a Function or Subroutine. In most complex scripts you probably
> wouldn't even know the data you are looking for until you were into a
> subroutine or function.
>
> Any help would be greatly appreciated.
>
> Jim Winner
> Program Manager
> The Catholic University of America


Re: Error handling bug on GetObject? by JamesWinner

JamesWinner
Wed Jul 12 06:06:02 CDT 2006

Thanks. I had missed that aspect of error trapping. I'll test to see if
that is what is happening here. It would still represent inconsistent
behavior, in that my scripts rely heavily on error trapping and this is the
only time I've run into this. But I'll do some sample scripts to see if
there is a consistent pattern where error trapping works globally and where
it doesn't.

Thanks again!

Jim W.

"Tom Lavedas" wrote:

> I believe the documentation covers this (but you have to read
> carefully) and it's not a bug. The issue is the context of the error
> handler. That is, the error handler you invoke at the top level of
> your procedure is Not global to another routine called from it. You
> need to invoke error handling specific to each function of subroutine
> you might call from your main procedure.
>
> Tom Lavedas
> ============
> http://members.cox.net/tglbatch/wsh
>
> James Winner wrote:
> > Hi,
> >
> > I seem to have hit a bug in the error handling of VBScript. I ran into the
> > problem when trying to assign a user to a group, but the group doesn't exist.
> > If Error Handling is not turned on, then the script crashes on the GetObject
> > statement as expected. However, I want to catch and log the error, and
> > continue on with the script. So, I used the normal code:
> >
> > Set objGroup = GetObject("LDAP://cn=Sales,cn=Users,dc=fabrikam,dc=com")
> > If Err.Number <> 0 Then
> > WScript.Echo "Error - unable to bind to group"
> > Else
> > WScript.Echo "Group bound"
> > End If
> >
> > In a main routine, this code behaves exactly as expected. However, if I put
> > this code into a Function, like so:
> >
> > On Error Resume Next
> >
> > If SetGroup() Then
> > WScript.Echo "Set Group Fine"
> > Else
> > WScript.Echo "Set Group Failed"
> > End If
> >
> > Function SetGroup()
> >
> > SetGroup = FALSE
> >
> > set objGroup = GetObject("LDAP://cn=Sales,cn=Users,dc=fabrikam,dc=com")
> > WScript.Echo "Did we get to this line?"
> > If Err.Number <> 0 Then
> > WScript.Echo "Error"
> > SetGroup = FALSE
> > Else
> > WScript.Echo "Fine"
> > SetGroup = TRUE
> > End If
> >
> > End Function ' Set Group
> >
> > The Error Handling code no longer runs. Instead the Script drops out of the
> > function back to the main routine. The WScript.Echo directly after the
> > GetObject was added to verify that the problem was on the GetObject line, not
> > with the Error Handling afterwards. In this simplified sample program, the
> > program does not crash at the GetObject (though it will, as expected, without
> > the On Error Resume Next), instead it simply drops back to the main routine.
> > In this particular case, reporting "Set Group Fine".
> >
> > The full script where I ran into this problem is much more complicated, and
> > the GetObject is in nested routines. The main routine calls a subroutine,
> > which calls another subroutine, which calls the function that contains the
> > GetObject statement. In this complex program, the script drops all the way
> > back to the main routine, not just out of the Function.
> >
> > So far, I have not found any code examples for testing for the existence of
> > a Group the way I can test for the existence of a file. With the GetObject's
> > incorrect behavior when an error occurs I'm not even sure how such a test can
> > be written and incorporated into real-world scripts, as such error handling
> > belongs in a Function or Subroutine. In most complex scripts you probably
> > wouldn't even know the data you are looking for until you were into a
> > subroutine or function.
> >
> > Any help would be greatly appreciated.
> >
> > Jim Winner
> > Program Manager
> > The Catholic University of America
>
>

Re: Error handling bug on GetObject? by JamesWinner

JamesWinner
Wed Jul 12 06:35:02 CDT 2006

Well, well. That wasn't how I had interpreted error trapping, but you do
seem to have it right on the money. I tested it with the following simple
script:

On Error Resume Next

If TestFunc() Then
WScript.Echo "All is right with the world."
Else
WScript.Echo "Computers are just evil."
End If

Function TestFunc()

TestFunc = FALSE

NoSuchSub()

If Err > 0 Then
WScript.Echo Err.Number & " " & Err.Description
Err.Number = 9999
Err.Description = "A call has been made to a non-existent subroutine. "
& _
"Please report this to the programmer, as there is most likely a
typo " & _
"in the code."
WScript.Echo "Error: " & Err.Number & " - " & Err.Description
End If

End Function

Now, just because something is documented doesn't mean it isn't a bug.
Where a global On Error Resume Next should "resume" to I'll admit can be
debated. However, in the above code the error drops back to the main routine
with a Function return value of TRUE. Documented or not, that I judge to be
a bug.

But thanks for the help. I will recode accordingly.

Jim W.

"Tom Lavedas" wrote:

> I believe the documentation covers this (but you have to read
> carefully) and it's not a bug. The issue is the context of the error
> handler. That is, the error handler you invoke at the top level of
> your procedure is Not global to another routine called from it. You
> need to invoke error handling specific to each function of subroutine
> you might call from your main procedure.
>
> Tom Lavedas
> ============
> http://members.cox.net/tglbatch/wsh
>


Re: Error handling bug on GetObject? by Tom

Tom
Wed Jul 12 07:38:48 CDT 2006

The ad hoc nature of script code, makes global error handling
problematic, as you pointed out. Therefore, the published error
handling approach, while not particularly convienient, is the only
thing that is reasonable to implement (I would assume). Thus, IMHO it
does not qualify as a bug. I do think the documentation does leave a
lot to be desired on this and a number of other subjects, but remember
- its all provided 'free'. (Or at least you don't pay extra for it. ;^)

Tom Lavedas
=============
http://members.cox.net/tglbatch/wsh

James Winner wrote:
> Well, well. That wasn't how I had interpreted error trapping, but you do
> seem to have it right on the money. I tested it with the following simple
> script:
{snip}>
> Now, just because something is documented doesn't mean it isn't a bug.
> Where a global On Error Resume Next should "resume" to I'll admit can be
> debated. However, in the above code the error drops back to the main routine
> with a Function return value of TRUE. Documented or not, that I judge to be
> a bug.
>
> But thanks for the help. I will recode accordingly.
>
> Jim W.
>
> "Tom Lavedas" wrote:
>
> > I believe the documentation covers this (but you have to read
> > carefully) and it's not a bug. The issue is the context of the error
> > handler. That is, the error handler you invoke at the top level of
> > your procedure is Not global to another routine called from it. You
> > need to invoke error handling specific to each function of subroutine
> > you might call from your main procedure.
> >
> > Tom Lavedas
> > ============
> > http://members.cox.net/tglbatch/wsh
> >


Re: Error handling bug on GetObject? by JamesWinner

JamesWinner
Wed Jul 12 08:34:02 CDT 2006

I am curious where you have found this documented. I can't find it in either
of the 2 Microsoft Press books I have (Windows 2000 Scripting Guide, and
Scripting Self Paced Learning). As a matter of fact, their Learning Guide's
presentation of error handling would lead you to believe it behaves as I
thought it did. The show it as a standard part of a header section in a
script, and suggest commenting it out during development.

This type of approach is what I used to teach in the dark ages for adding
debugging code, where you set a flag at the beginning of the program to turn
debugging messages on and off.

I have found reference in a 3rd party book that On Error Resume Next
"behaves like variables" and can be over-ridden in routines. Also that End
Sub and End Function clear Err, as Err.Clear does. While this wouldn't have
led me to expect the behavior I saw, I can see it in retrospect.

I'd like to find more documentation on this because I still don't understand
why, if a Function's return value has been set to FALSE prior to the error,
it seems to be treated as TRUE when On Error Resume Next causes processing to
drop out of the routine. It makes me wonder what other actions that had been
done in the routine are dropped.

Curiouser and curiouser...

Thanks again. Very helpful info!

Jim W.


"Tom Lavedas" wrote:

> The ad hoc nature of script code, makes global error handling
> problematic, as you pointed out. Therefore, the published error
> handling approach, while not particularly convienient, is the only
> thing that is reasonable to implement (I would assume). Thus, IMHO it
> does not qualify as a bug. I do think the documentation does leave a
> lot to be desired on this and a number of other subjects, but remember
> - its all provided 'free'. (Or at least you don't pay extra for it. ;^)
>
> Tom Lavedas
> =============
> http://members.cox.net/tglbatch/wsh
>
> James Winner wrote:
> > Well, well. That wasn't how I had interpreted error trapping, but you do
> > seem to have it right on the money. I tested it with the following simple
> > script:
> {snip}>
> > Now, just because something is documented doesn't mean it isn't a bug.
> > Where a global On Error Resume Next should "resume" to I'll admit can be
> > debated. However, in the above code the error drops back to the main routine
> > with a Function return value of TRUE. Documented or not, that I judge to be
> > a bug.
> >
> > But thanks for the help. I will recode accordingly.
> >
> > Jim W.
> >
> > "Tom Lavedas" wrote:
> >
> > > I believe the documentation covers this (but you have to read
> > > carefully) and it's not a bug. The issue is the context of the error
> > > handler. That is, the error handler you invoke at the top level of
> > > your procedure is Not global to another routine called from it. You
> > > need to invoke error handling specific to each function of subroutine
> > > you might call from your main procedure.
> > >
> > > Tom Lavedas
> > > ============
> > > http://members.cox.net/tglbatch/wsh
> > >
>
>

Re: Error handling bug on GetObject? by Walter

Walter
Wed Jul 12 09:02:12 CDT 2006

Actually, believe it or not, everything in your example worked as it should.
A function will only return a value if it executes completely. If an error
forces it to abort, then it will not return anything. The "On Error Resume
Next" statement in your example masked this. What happened when the function
returned is that the main routine was still in the middle of an IF
statement. Without error trapping it would have exited the IF statement with
an error. Instead, the "On Error Resume Next" statement forces it to
execute one of the conditions in the IF statement. And guess what it does?
It executes the first condition that it sees. It will ALWAYS execute the
first condition that it sees. You can test this yourself by switching the
WScript.echo statements around.

"James Winner" <JamesWinner@discussions.microsoft.com> wrote in message
news:4DD83987-78EF-4FA6-8C3F-215975AE81FE@microsoft.com...
> Well, well. That wasn't how I had interpreted error trapping, but you do
> seem to have it right on the money. I tested it with the following simple
> script:
>
> On Error Resume Next
>
> If TestFunc() Then
> WScript.Echo "All is right with the world."
> Else
> WScript.Echo "Computers are just evil."
> End If
>
> Function TestFunc()
>
> TestFunc = FALSE
>
> NoSuchSub()
>
> If Err > 0 Then
> WScript.Echo Err.Number & " " & Err.Description
> Err.Number = 9999
> Err.Description = "A call has been made to a non-existent subroutine.
> "
> & _
> "Please report this to the programmer, as there is most likely a
> typo " & _
> "in the code."
> WScript.Echo "Error: " & Err.Number & " - " & Err.Description
> End If
>
> End Function
>
> Now, just because something is documented doesn't mean it isn't a bug.
> Where a global On Error Resume Next should "resume" to I'll admit can be
> debated. However, in the above code the error drops back to the main
> routine
> with a Function return value of TRUE. Documented or not, that I judge to
> be
> a bug.
>
> But thanks for the help. I will recode accordingly.
>
> Jim W.
>
> "Tom Lavedas" wrote:
>
>> I believe the documentation covers this (but you have to read
>> carefully) and it's not a bug. The issue is the context of the error
>> handler. That is, the error handler you invoke at the top level of
>> your procedure is Not global to another routine called from it. You
>> need to invoke error handling specific to each function of subroutine
>> you might call from your main procedure.
>>
>> Tom Lavedas
>> ============
>> http://members.cox.net/tglbatch/wsh
>>
>



Re: Error handling bug on GetObject? by Tom

Tom
Wed Jul 12 09:10:56 CDT 2006

I found the reference in the VBScript documentation that comes with the
WSH downloadable documentation (available at:
http://www.microsoft.com/downloads/details.aspx?FamilyId=01592C48-207D-4BE1-8A76-1C4099D7BBB9&displaylang=en)

I also found it on-line at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/0675d0b2-5c1a-4f20-94f3-6749c74984a9.asp.

But, as I said, its a bit obscure. The fourth paragraph of the
description of On Error reads:

"An On Error Resume Next statement becomes inactive when another
procedure is called, so you should execute an On Error Resume Next
statement in each called routine if you want inline error handling
within that routine. When a procedure is exited, the error-handling
capability reverts to whatever error-handling was in place before
entering the exited procedure."

This only implies that global error handling is not supported, without
coming right out and saying it. BTW, global error handlers ARE
supported in VB and VBA (VB for applications), just not in VBScript.

As for the aberrant behavior of the exit from the function, I would not
have expected that and seem to remember having done otherwise, but I
didn't look at the example you provided. I don't have time at the
moment to persue it, but will try to give a look later.

Tom Lavedas

James Winner wrote:
> I am curious where you have found this documented. I can't find it in either
> of the 2 Microsoft Press books I have (Windows 2000 Scripting Guide, and
> Scripting Self Paced Learning). As a matter of fact, their Learning Guide's
> presentation of error handling would lead you to believe it behaves as I
> thought it did. The show it as a standard part of a header section in a
> script, and suggest commenting it out during development.
>
> This type of approach is what I used to teach in the dark ages for adding
> debugging code, where you set a flag at the beginning of the program to turn
> debugging messages on and off.
>
> I have found reference in a 3rd party book that On Error Resume Next
> "behaves like variables" and can be over-ridden in routines. Also that End
> Sub and End Function clear Err, as Err.Clear does. While this wouldn't have
> led me to expect the behavior I saw, I can see it in retrospect.
>
> I'd like to find more documentation on this because I still don't understand
> why, if a Function's return value has been set to FALSE prior to the error,
> it seems to be treated as TRUE when On Error Resume Next causes processing to
> drop out of the routine. It makes me wonder what other actions that had been
> done in the routine are dropped.
>
> Curiouser and curiouser...
>
> Thanks again. Very helpful info!
>
> Jim W.
>
>
> "Tom Lavedas" wrote:
>
> > The ad hoc nature of script code, makes global error handling
> > problematic, as you pointed out. Therefore, the published error
> > handling approach, while not particularly convienient, is the only
> > thing that is reasonable to implement (I would assume). Thus, IMHO it
> > does not qualify as a bug. I do think the documentation does leave a
> > lot to be desired on this and a number of other subjects, but remember
> > - its all provided 'free'. (Or at least you don't pay extra for it. ;^)
> >
> > Tom Lavedas
> > =============
> > http://members.cox.net/tglbatch/wsh
> >
> > James Winner wrote:
> > > Well, well. That wasn't how I had interpreted error trapping, but you do
> > > seem to have it right on the money. I tested it with the following simple
> > > script:
> > {snip}>
> > > Now, just because something is documented doesn't mean it isn't a bug.
> > > Where a global On Error Resume Next should "resume" to I'll admit can be
> > > debated. However, in the above code the error drops back to the main routine
> > > with a Function return value of TRUE. Documented or not, that I judge to be
> > > a bug.
> > >
> > > But thanks for the help. I will recode accordingly.
> > >
> > > Jim W.
> > >
> > > "Tom Lavedas" wrote:
> > >
> > > > I believe the documentation covers this (but you have to read
> > > > carefully) and it's not a bug. The issue is the context of the error
> > > > handler. That is, the error handler you invoke at the top level of
> > > > your procedure is Not global to another routine called from it. You
> > > > need to invoke error handling specific to each function of subroutine
> > > > you might call from your main procedure.
> > > >
> > > > Tom Lavedas
> > > > ============
> > > > http://members.cox.net/tglbatch/wsh
> > > >
> >
> >


Re: Error handling bug on GetObject? by ekkehard

ekkehard
Wed Jul 12 11:03:44 CDT 2006

James Winner wrote:
> Well, well. That wasn't how I had interpreted error trapping, but you do
[...]
> Now, just because something is documented doesn't mean it isn't a bug.
> Where a global On Error Resume Next should "resume" to I'll admit can be
> debated. However, in the above code the error drops back to the main routine
> with a Function return value of TRUE. Documented or not, that I judge to be
> a bug.
[...]
Some code:

1: Option Explicit
2:
3: Dim sArg : sArg = "no arg"
4: Dim sRet, aErr
5:
6: If 1 = WScript.Arguments.Count Then sArg = WScript.Arguments( 0 )
7:
8: On Error Resume Next
9: sRet = updateRemoteDB( sArg )
10: aErr = saveErr()
11: On Error GoTo 0
12:
13: If 0 = aErr( 0 ) Then
14: WScript.Echo "Result of Update: ", sRet
15: Else
16: WScript.Echo "Maincode", aErr( 0 ), aErr( 1 ), aErr( 2 )
17: End If
18: WScript.Quit aErr( 0 )
19:
20: Function saveErr()
21: saveErr = Array( Err.Number, Err.Source, Err.Description )
22: Err.Clear
23: End Function
24:
25: Function updateRemoteDB( sArg )
26: Dim aErr
27:
28: updateRemoteDB = "Internal error in updateRemoteDB()"
29:
30: Select Case LCase( sArg )
31: Case "no arg" ' user error, anticipated and cared for
32: updateRemoteDB = "nix - please specify 'normal', 'miss' or 'except' ."
33: Case "normal", "except", "miss"
34: If existsFile( sArg ) Then
35: On Error Resume Next
36: updateDB sArg
37: aErr = saveErr()
38: On Error GoTo 0
39: If 0 <> aErr( 0 ) Then
40: Err.Raise aErr( 0 ), aErr( 1 ), aErr( 2 )
41: End If
42: ' deleteTmpDB, generateInvoice
43: updateRemoteDB = "remote.mdb updated."
44: Else
45: updateRemoteDB = "didn't update, remote.mdb not found, try again later."
46: End If
47: Case Else ' user error, anticipated and cared for
48: updateRemoteDB = "nix - please specify 'normal', 'miss' or 'except' instead
of '" + sArg + "'."
49: End Select
50:
51: End Function
52:
53: Function existsFile( sArg )
54: existsFile = ("miss" <> sArg)
55: End Function
56:
57: Sub updateDB( sArg )
58: If "except" = sArg Then
59: Err.Raise vbObjectError + 4711, "updateDB: ", "remote.mdb has size 0"
60: End If
61: End Sub
62:

Some output:

(a) C:\wis\_vbs\0506\dev\forum
cscript terror.vbs
Result of Update: nix - please specify 'normal', 'miss' or 'except' .

(b) C:\wis\_vbs\0506\dev\forum
cscript terror.vbs normal
Result of Update: remote.mdb updated.

(c) C:\wis\_vbs\0506\dev\forum
cscript terror.vbs miss
Result of Update: didn't update, remote.mdb not found, try again later.

(d) C:\wis\_vbs\0506\dev\forum
cscript terror.vbs except
Maincode -2147216793 updateDB: remote.mdb has size 0

Some remarks:

(1) 'compile time' errors should cause an immediate abort. They can be corrected
and that's it. If I write

If 1 == WScript.Arguments.Count Then sArg = WScript.Arguments( 0 )

the script won't run until I correct my error. That's good.

(2) 'stupid programmer's errors' - e.g.

If l = WScript.Arguments.Count Then sArg = WScript.Arguments( 1 )

are caught at runtime if you

(i) Put an "Option Explicit" in the first line of your script
(ii) Don't use "On Error Resume Next" globally

Nobody forces you to do that; some books and the Scripting Guys suggest
otherwise, but I think to violate these rules is bad practice.

(3) some 'runtime problems' can and should be anticipated; they can be solved
by 'normal' code: user input and missing files are typical examples. If
you check the conditions carefully there is no reason to worry. (see
output (a) and (c))

(4) some 'runtime problems' can't be handled in a 'normal' way. There were
some questions in this group like 'How do I test for the existence of a
file before I try to get it via ftp, do a oConnection.Open on it, ...?'
lately. While it is necessary (and laudable) to check before you act,
it isn't a sufficient condition for success. There is no guaranty
that the Admin doesn't delete your file between oFS.FileExist() and
oFS.ReadLine(). To avoid a crash of the script (and get some output
like (d)), you have to use "On Error Resume Next", because you can't
add some If statements to the code of oFS.ReadLine(). To restrict the
scope of "OERN" you must save the current state of the global Err object
(lines 10, 22 ff, 37); after that you may react to 'nasty' errors
with 'standard' code. Perhaps

39: If 0 <> aErr( 0 ) Then
40: Err.Raise aErr( 0 ), aErr( 1 ), aErr( 2 )
41: End If
42: ' deleteTmpDB, generateInvoice
43: updateRemoteDB = "remote.mdb updated."

should be rewritten as:

39: If 0 = aErr( 0 ) Then
' deleteTmpDB, generateInvoice
updateRemoteDB = "remote.mdb updated."
Else
Err.Raise aErr( 0 ), aErr( 1 ), aErr( 2 )
End If

If you want to handle the error in the calling code, you have to Raise
the error again (that was missing from James Winner's code).

(4) If "On Error Resume Next" would be effective in called Subs/Functions
you couldn't have 'out of OERN' code in the callee and OERN code in
caller. That's why I think scoping the OERN is no bug, but a good idea.

(5) I wouldn't argue against "If you need exception handling, choose a language
that supports it; if you want cheap/quick&dirty scripts, accept that they
will crash under exceptional conditions", but I hope the code sample shows
that you can do reasonable/sensible errorhandling in VBScript.