After my message yesterday, I updated my strategy a little bit.
Yesterday, I added the code to my global error handler that is always called by vbWatchdog. I created a Call Stack string variable every time there was an error regardless of how it was going to get handled.
This worked for the time being, but I discovered that I had some routines that were using error handlers to ignore certain errors. Say to see if a file exists, a routine is trying to access the file properties and knows it’s not there if it gets a certain error. Generally wouldn’t be a big deal for single cases like this. I timed the Call Stack traversal and it was taking it about 0.002 – 0.005 seconds on my dev machine. That’s not too bad, but I am sometimes looping through objects and determining whether a section exists in a report by checking an array from 1 to 100 on the section number. This generally produces upwards of 90 errors and can end up running several times. It is pretty unnoticeable when I’m using it without the call stack, but as soon as I added the call stack I noticed a significant slowdown in the form of multiple seconds due to the sheer number of times this error is being handled and the call stack string being built, and it wasn’t been used because it’s a throw away error. (Yes, I’m sure I could work on the efficiency of that loop, but that will be for another day).
In general, I decided it would be better to create the call stack only when needed. This meant I needed to pass the ErrCallStack object to the routine that does the logging which is in the library database. So I got that all set up and tested it and I got a vbWatchdog error stating that I was calling ErrCallStack outside of the global error routine. I initially thought all was lost, but then I discovered that what was actually throwing the error was only when I tried to retrieve the code line. Ok, so I left the code as is and removed the portion of the log with the actual code line for now. That will still allow me to lookup what is running by module name, procedure name, and line number. This will still give me a major leg up when debugging this application.
Jonathan, are you checking the ErrEx.State value in your global vbWatchdog error handler? With that value, you can immediately exit the error handler if the ErrEx.State is set to `OnErrorResumeNext`. That should avoid the slowdown of looping through the call stack when you won’t be doing anything with it anyway.
Thanks for the tip. In our app template we do use all the the various states and have the ability to set how our app will handle them by setting different configuration options in the app. Generally these options are different when the app is in development vs when the app is in production. The global error handler is storing some of the information to make it available for later error handling logic in the app itself (vs the template). The app can utilize the system to log the error which is in a completely different function in a library file.
Hey Jonathan, also consider setting the `ErrEx.IgnoreHandledErrors` value to True in your startup routine. That way, your global error handler won’t be triggered at all for error states such as `OnErrorResumeNext` or `OnErrorGotoLabel`.
Thanks Wayne,
I didn’t remember that flag. Very nice feature. Can the local error handler still call on the ErrEx object to get advanced info? Or does that not get populated when ignoring handled errors?