Access: Crash Reporter / Error mailer

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • TheSmileyCoder
    Recognized Expert Moderator Top Contributor
    • Dec 2009
    • 2322

    Access: Crash Reporter / Error mailer

    Introduction
    This is my crash reporter tool, version 1.0. It has already gone through a lot of changes since the beta version, and I still have features and stuff I wish to add, but I think it is time to start letting others use it. For download links, see the bottom of this page.


    What is this Crash Reporter?
    If you have worked with users for a while you have probably found out that they are not always the most reliable source of information for details on error reporting.

    If you (the developer) are sitting in the same building, they might just swing by, and have you come take a look at their monitor. But what if they are in another building, or another city? Well a few options could occur:
    • They never report the error to you and just continue to try to use the program, but eventually get tired of getting the same error and blame you, even though they actually did not do anything to give you a chance to correct the error.

    • They send you an email or phone you up, and this might be an example of the dialogue to take place:
      • User/Client: “Hey Developer, we had an error”.
      • Developer : “Okay, can you tell me what the error number was?”
      • User/Client: “I think it started with a 6, or maybe a 7″
      • Developer: “Hmm. ok, what were you doing at the time?”
      • User/Client: “I was working in the tool”
      • Developer “Yes, but which screen or form were you using?”
      • User/Client: “The one with the big textbox for details!”
      • Developer: “Okay, what did you do right before the error occurred?”
      • User/Client: “I was browsing the internet”
      • Developer: “I meant in the application”
      • User/Client: “Oh, I think I was updating a customer record”

    • (rare) They take a screenshot and write a detailed error report saying what they were doing, and include relevant details about the error number, error description and what else they might have been doing just before.


    Now imagine how nice it would be if every user did option 3. But wait, what if we could help turn regular users into those super users? The good news is that, now you can! With this free piece of software you can now present a pretty looking error form and AUTOMATICALLY generate detailed and useful error reports including screenshots of all your open forms and the application.

    Form example
    This is the form as presented to the user. Of course you can modify it to look as you please.
    [IMGnothumb]http://thesmileycoder. com/wp-content/uploads/2013/03/ErrorReporterFo rmScreenshot.pn g[/IMGnothumb]



    Example of error report:

    Code:
    Error ID:F9AE94266E3943DBB1D664959A33868F
    ==== Error Message as presented to user ====
    Error 91 has occurred in procedure [cmdCauseError_Click] in module [TSC_ErrRep_frm_Test_ErrorReportTool]
    Object variable or With block variable not set
    
    This error was raised in order to test the Error report functionality
    
    ==== Error Number ====
    91
    
    ==== Error Line (0 if N/A) ====
    0
    
    ==== Error Description ====
    Object variable or With block variable not set
    
    ==== Error in Module ====
    TSC_ErrRep_frm_Test_ErrorReportTool
    
    ==== Error in Procedure ====
    cmdCauseError_Click
    
    ==== Session Information ====
    ==== Application Information ====
    Name : TSC_ErrorReporter – BETA.mdb
    Path : C:\Users\Documents\Applications\ErrorReport\TSC_ErrorReporter – BETA.mdb
    Active Form : TSC_ErrRep_frm_Test_ErrorReportTool
    Active Control : cmdCauseError
    Parent Form(if any) : TSC_ErrRep_frm_Test_ErrorReportTool
    Active Datasheet : N/A
    Active Report : N/A
    Open forms : TSC_ErrRep_frm_Test_ErrorReportTool
    
    ==== Access Info ====
    Version : 14.0
    Build : 6024
    Fileformat : 10
    DB Version : 4.0
    ==== Time of Error ====
    15-03-2013 15:01:55
    
    ==== Windows User Name ====
    aec
    
    ==== Active Form ====
    TSC_ErrRep_frm_Test_ErrorReportTool
    
    ==== Active Control ====
    cmdCauseError
    
    ==== Active Control Parent Form ====
    TSC_ErrRep_frm_Test_ErrorReportTool
    
    ==== Active Data Sheet ====
    N/A
    
    ==== Active Report ====
    N/A
    
    ==== All Open Forms ====
    TSC_ErrRep_frm_Test
    
    ==== Application Version ====
    1.0
    
    ==== TheSmileyCoders Crash Reporter Version Info ====
    1.0
    
    ==== Application Version ====
    1.0
    
    ==== Minutes application has been running ====
    157
    
    ==== Hours since last Windows reboot ====
    7
    What else can it do?

    All error information is also stored in a table. This table can be local or networked(If networked switch dbOpenTable to dbOpenDynaset). The error report is of course error resistant so even if no connection is available to the network, the reporter will continue, and store all the information into a text-based log file, which can be emailed along with the screenshots to your email!

    Email Options

    TheSmileyCoders Crash Reporter is setup to use either Outlook or CDO (with Gmail). To use the built in CDO you need to have a Gmail account setup that you can use for this purpose, however if you are more experienced in CDO, you should be able to setup the Crash Reporter to use other email accounts. Screenshots and error log are automatically attached.

    That sounds expensive!

    Nope, I have chosen to provide this tool absolutely free of charge, under the Creative Commons 3.0 license. For more details see http://creativecommons.org/licenses/by/3.0/. This means that you may use, alter, copy, redistribute and include this code in your application, provided that you include the attribution details specified in each module.



    Why is that? Well, maybe I could sell this tool for some nice money, but the fact is that I want to give something back to the Access community which has helped me learn and evolve to the point where writing such an application is possible, and also because I would rather see my hard work being put to good use, and because I am not big on marketing. But hey, when that first error report ticks into your mailbox, if you find my Crash Reporter useful, why not drop a thank you comment on my blog? Those comments are the real return-value for me.




    Setup and Use

    For setup information, you can watch this YouTube video, and/or read on:
    http://www.youtube.com/watch?v=V08Utrd2Xgo


    Before you start using the Crash Reporter, you need to modify the following settings found in the TSC_ErrRep_Main module. I have highlighted the areas that need to be set if you use Outlook as your email client.

    Code:
    ‘***************************************************************************************
    ‘ – Err reporter settings
    ‘***************************************************************************************
    
    ‘Place YOUR email here, the email which the reports should be sent to
    Public Const gReportErrorToEmail As String = “YourEmail@SomeWhere.com”
    
    ‘Place the name of your application in here. It will be used in various message boxes and captions
    Public Const gAppName As String = “TheSmileyCoders Report Tool”
    
    ‘Place the name of your company, or your own name here
    Public Const gDeveloperName As String = “TheSmileyCoder”
    
    ‘Choose whether to use Outlook or CDO for mail
    Public Const gUseOutlook As Boolean = True
    
    ‘Place details on the Gmail account for which to use CDO to send error message
    Public Const gSendUserName As String = “”
    Public Const gSendPassword As String = “”
    
    ‘Set whether or not to take a screenshot, and whether to include it per default
    Public Const gTakeScreenshot As Boolean = True
    Public Const gDefaultSubmitScreenshot As Boolean = True
    
    ‘Whether or not to dim the background as the submit error form is opened
    Public Const gDimBackground As Boolean = True ‘Default is true
    
    ‘Version of Error report tool in use
    Public Const gErrorReportToolVersion As String = “1.0″
    
    If you want to use CDO instead, so you don’t have to rely on the user having outlook installed, you can modify the following settings:
    
    ‘Choose whether to use Outlook or CDO for mail
    Public Const gUseOutlook As Boolean = False
    
    ‘Place details on the gmail account for which to use CDO to send error msg
    Public Const gSendUserName As String = “YourExtraEmail@gmail.com”
    Public Const gSendPassword As String = “YourPassword“
    I would suggest not using your own gmail, but creating a Gmail account specifically for this purpose.



    Now with the settings in place, you need to import all the objects from the sample database, into your application. The only object that is not required is the test form. Once imported, start by checking that it compiles fine within your environment, by selecting Debug->Compile in the VBA editor. Then you need to look at your error handling procedures, and modify them to use the error report tool. Now if you already have error handling code, it might look something like this:

    Code:
    Private Sub YourCode()
    On Error goto ErrHandler
     
     'Some code
     
    ExitSub:
      Exit Sub
     
    ErrHandler:
      Msgbox Err.Number & " - " & err.Description
      Resume ExitSub
     
    End Sub
    Now instead of that plain old message box saying there has been an error, you can now use the Error reporter. Simply replace the MsgBox line with:

    Code:
    TSCs_ReportUnexpectedError "Name of your procedure", "Name of module or form", "Custom info"
    and the tool will handle the rest, including taking screenshots, preparing the error report, and opening the error report form.

    Summary

    In this post I presented my new Crash Reporter. With this you can easily get much more detailed and useful information when a bug/error occurs in your software, and users get presented with a much nicer looking custom form, instead of the plain old windows message box.

    The download comes with a test form, so you can start experimenting with the Crash Reporter today!

    Download

    TheSmileyCoders Crash Reporter Version 1.0


    Known Issues

    If you are using tabbed forms in your access application the Crash Reporter will sometimes only take a screenshot of the topmost (the visible/active) form.

    I have heard reports that it does not currently work on windows 8, but without access to windows 8 myself I can't test it.
    Last edited by TheSmileyCoder; Apr 8 '13, 09:28 AM.
  • MMcCarthy
    Recognized Expert MVP
    • Aug 2006
    • 14387

    #2
    Thanks Smiley, I will definitely find this one useful :) I'll be implementing it on my next project and will give you feedback when it's running with the client. Probably won't be for a while. I think it may become one of my "must have" tools.

    Comment

    • Meetee
      Recognized Expert Contributor
      • Dec 2006
      • 928

      #3
      Great Smiley, seems very useful and nicely described!

      Where is Thumb Up button? :)

      Comment

      • Seth Schrock
        Recognized Expert Specialist
        • Dec 2010
        • 2965

        #4
        @Smiley I had read that it wasn't the best idea to send error messages as emails as it created a risk of an error occurring in the error handler which would either cause an infinite loop if the error was handled or make it so that the error message was lost if the error wasn't handled. What is your opinion on this?

        Comment

        • TheSmileyCoder
          Recognized Expert Moderator Top Contributor
          • Dec 2009
          • 2322

          #5
          @Mary and Meetee
          Thank you for your feedback, I hope you find it useful.

          @Seth:
          None of the functions used in the tool call the Error Mailer. So you should not enter a infinite loop. Furthermore I have used alot of time to setup the mailer so that it is "error resistent", I.e. it will continue to run til it reaches the end. Some of the information collection routines are setup so that if they should error, they will simply return something like:
          "Access Version: Error getting Access Version"

          Of course you are correct that it is a issue that merits consideration, but I do believe I have tried to take into consideration within the code.

          Comment

          • Seth Schrock
            Recognized Expert Specialist
            • Dec 2010
            • 2965

            #6
            Great! I will add this to my database that I'm about to roll out and see how it works.

            I guess the real trick is to make it so that you don't need the error handler very often :)

            Comment

            • Lysander
              Recognized Expert Contributor
              • Apr 2007
              • 344

              #7
              This looks a fantastic idea. Two questions.
              1)Is your application itself written in Ms-Access VBA or in Visual Basic (what I don't have)
              2) Is it possible to have the report saved to a file on the generating pc, to be emailed independtly. The reason for this is most of my users are on laptops out in the field, with no telephone, no internet, indeed no electricity, so they would need to save the error report, and then email once they get back to base and have access to the internet.

              Very interesting idea.

              Comment

              • Seth Schrock
                Recognized Expert Specialist
                • Dec 2010
                • 2965

                #8
                This is incredible Smiley. I just tried it out and I love it. The only thing is that sometimes it takes several seconds from clicking the button to getting the error form open. Sending the email goes quick. I love all the information that it gathers along with the screen shots. It sure seems "user proof" to me :)

                Comment

                • TheSmileyCoder
                  Recognized Expert Moderator Top Contributor
                  • Dec 2009
                  • 2322

                  #9
                  @Lysander
                  1) It is written in Access VBA. It does also rely on several windows API calls, but nothing besides that. Everything is visible and available in the sample. The zip is not code-locked.

                  2) The textual part of the report and the images are saved to the users temp folder (I am guessing that is the least likely folder path to be restricted access by IT, but it is really just a guess). There is actually a function in there that checks for internet connectivity (Although it can be fooled by being connected to a LAN that doesn't have internet if I recall correctly). Anyways, you could probably use that and store whether the report has been sent or not. There is no built-in support for it yet though. I did once have a simpler error reporter which didn't take screenshots. It stored all errors locally, and then each time during startup it would try to transfer all local errors to a server table, and if successful delete them from the local table. So it is certainly doable. I don't think its something I will build in any time soon though. Too many other projects I find more interesting :)

                  Comment

                  • TheSmileyCoder
                    Recognized Expert Moderator Top Contributor
                    • Dec 2009
                    • 2322

                    #10
                    @Seth
                    Did you enable the WMI information gathering? That function takes quite a bit of time. If you have linked backend access tables which are not available I also imagine it could take a bit of time to run, since it times out on trying to collect information on them.

                    Comment

                    • Seth Schrock
                      Recognized Expert Specialist
                      • Dec 2010
                      • 2965

                      #11
                      In my actual database, my backend is SQL Server, but it was running slow even testing on your database. How do you disable the WMI information gathering? I could probably do without that part if it would speed it up.

                      Comment

                      • TheSmileyCoder
                        Recognized Expert Moderator Top Contributor
                        • Dec 2009
                        • 2322

                        #12
                        Running on my own PC, the information and screenshots is collected in less then 0.2 seconds. I wonder what is taking up time on your machine.

                        In the module "TSC_ErrRep_Mai n", try searching for "TSCf_CollectWM IInfo".
                        It is disabled (commented out) by default. I included it for fun, and since it might be useful under certain circumstances.

                        If I get the time, I might write a timer function that times the different procedure calls so you can see which parts take up time. Right now however I am working on subtitling part 5 of my treeview series.

                        Comment

                        • Seth Schrock
                          Recognized Expert Specialist
                          • Dec 2010
                          • 2965

                          #13
                          Yep, it is still commented out. I think that you have posted a timer previously which I have used. I'll play with that and dig through and see where all I should put it.

                          I'm really excited about part 5 of the Treeview series!

                          Comment

                          • TheSmileyCoder
                            Recognized Expert Moderator Top Contributor
                            • Dec 2009
                            • 2322

                            #14
                            @Seth:
                            I cooked up a bit of code to try to narrow down which functions are taking time to run on your system.

                            If you paste the following API into the declaration section (Right below option explicit) of module TSC_ErrRep_Main :
                            Code:
                            Private Declare Function GetTickCount Lib "kernel32" () As Long

                            And then paste this at the bottom of the same module:
                            Code:
                            Public Function TSCf_Timed() As String
                            '---------------------------------------------------------------------------------------
                            '---------------------------------------------------------------------------------------
                            ' Procedure : TSCf_Timed
                            ' Author    : AEC - Anders Ebro Christensen / TheSmileyCoder
                            ' Date      : 2013-02-02
                            ' Version   : 1.0
                            ' Purpose   : If you find the collection of error information takes to long
                            '           : Try using this module to time which of the information function
                            '           : takes up the bulk of the time.
                            '---------------------------------------------------------------------------------------
                            '---------------------------------------------------------------------------------------
                               Dim lngTimeTotalStart As Long
                               Dim lngTimeStart As Long
                               Dim strReturn As String
                               Dim strResult As String
                               Dim strArray() As String
                               Dim strTotal As String
                               
                               
                               
                            
                               lngTimeTotalStart = GetTickCount
                               
                               lngTimeStart = GetTickCount
                                  strArray = TSCf_CaptureAllWindows("TimerTest")
                                  strResult = strResult & "TSCf_CaptureAllWindows:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                               
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_CollectSessionInfo
                                  strResult = strResult & "TSCf_CollectSessionInfo:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                               
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_GetWindowsLoginName
                                  strResult = strResult & "TSCf_GetWindowsLoginName:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                               
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_MinutesAppHasBeenRunning
                                  strResult = strResult & "TSCf_MinutesAppHasBeenRunning:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                            
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_HoursSinceLastWindowsBoot
                                  strResult = strResult & "TSCf_HoursSinceLastWindowsBoot:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                                  
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_CollectDatabaseProperties
                                  strResult = strResult & "TSCf_CollectDatabaseProperties:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                                  
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_CollectEnvironmentInfo
                                  strResult = strResult & "TSCf_CollectEnvironmentInfo:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                                  
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_CollectInternetConnectionInfo
                                  strResult = strResult & "TSCf_CollectInternetConnectionInfo:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                               
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_CollectBackendInformation
                                  strResult = strResult & "TSCf_CollectBackendInformation:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                               
                               lngTimeStart = GetTickCount
                                  strReturn = TSCf_CollectWMIInfo
                                  strResult = strResult & "TSCf_CollectWMIInfo:" & TSCf_EndTimer(lngTimeStart) & vbNewLine
                               
                               
                               
                               TSCf_Timed = strResult & vbNewLine & "Total time:" & TSCf_EndTimer(lngTimeTotalStart)
                            
                            End Function
                            
                            
                            Private Function TSCf_EndTimer(lngStartTime As Long) As String
                                Dim EndTime As Long
                                Dim ms As Integer
                                Dim s As Long
                            
                                EndTime = (GetTickCount - lngStartTime)
                                ms = EndTime Mod 1000
                                s = (EndTime - ms) / 1000
                                If s >= 1 Then
                                    TSCf_EndTimer = s & "s, " & ms & "ms"
                                Else
                                    TSCf_EndTimer = ms & "ms"
                                End If
                            
                            End Function
                            And call it from the immediate pane like so:
                            Code:
                            ? TSCf_Timed
                            you should see a result similar to this (When run on my PC):
                            Code:
                            TSCf_CaptureAllWindows:78ms
                            TSCf_CollectSessionInfo:0ms
                            TSCf_GetWindowsLoginName:0ms
                            TSCf_MinutesAppHasBeenRunning:0ms
                            TSCf_HoursSinceLastWindowsBoot:31ms
                            TSCf_CollectDatabaseProperties:62ms
                            TSCf_CollectEnvironmentInfo:0ms
                            TSCf_CollectInternetConnectionInfo:0ms
                            TSCf_CollectBackendInformation:47ms
                            TSCf_CollectWMIInfo:1s, 685ms
                            
                            Total time:1s, 903ms
                            In this case the TSCf_CollectWMI Info is taking up 90% of the time used, and that is partly why it is commented out as default. Without that the total time would be less then 200ms.

                            This times all the information collection routines, which I presume is what takes the most time. I haven't timed how long it takes to open and populate the form.

                            Please report back your findings, so we might get wiser :)

                            Comment

                            • Seth Schrock
                              Recognized Expert Specialist
                              • Dec 2010
                              • 2965

                              #15
                              I finally did your timer and found that the CaptureAllWindo ws portion is what is taking most of the time with 1s, 342ms. The WMI takes 2s, 512ms, but I don't have it running. The next highest is only 78ms hours since last reboot. I could probably turn this off, but really no need with so little time being taken.

                              Another question, how hard would it be to add ODBC error handler to this?

                              Comment

                              Working...