I'm developing an application with an error log when something goes bad. It must send an e-mail with the error details so I can remotely fix and upload a new update with the fix.
I'm using Try Catch Exception but I have a lot of methods to include this option in.
Is there another way to do it without doing so much code?
Since exceptions bubble up to the application instance try using the Application.SetUnhandledExceptionMode Method.
From above MSDN Link:
It is often not feasible to catch all of the exceptions thrown by
Windows Forms. Using this method, you can instruct your application
whether it should catch all unhandled exceptions thrown by Windows
Forms components and continue operating, or whether it should expose
them to the user and halt execution.
Public Shared Sub Main()
' Add the event handler for handling UI thread exceptions to the event.
AddHandler Application.ThreadException, AddressOf Form1_UIThreadException
' Set the unhandled exception mode to force all Windows Forms errors to go through
' our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
' Add the event handler for handling non-UI thread exceptions to the event.
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomain_UnhandledException
' Runs the application.
Application.Run(New Form1()) '' This is your applications Main Form
End Sub
Private Shared Sub Form1_UIThreadException(ByVal sender As Object, ByVal t As ThreadExceptionEventArgs)
'Put Error Handling Code here see the MSDN article for an example implementation
End Sub
Private Shared Sub CurrentDomain_UnhandledException(ByVal sender As Object, _
ByVal e As UnhandledExceptionEventArgs)
''Put Error Handling Code here see the MSDN article for an example implementation
End Sub
Sorry, misunderstood your question. Try putting your logic in a method and just try to call that method in every try catch statement you have.
Example:
Public Shared Sub Method1()
Try
'Method logic here
Catch ex As Exception
EmailError(ex)
End Try
End Sub
Public Shared Sub EmailError(ex As Exception)
'your remote error email logic here
End Sub
Related
I have another question considering events and exceptions
A small introduction to my project: I'm working in a 3 layer architecture, so I have a GUI(form), BLL(Business logic layer) and a DAL(data acces layer).
So my GUI is linked to a BLL which is connected to several DAL classes. For example my BLL has a class clsCSV (which reads and writes CSV files)
I now want to raise events and/or catch exceptions from this class to inform the user and log exceptions. There are 3 events: "ErrorLoad", "ErrorWrite", "Ready"
Public Class clsCSV
Public Sub New()
End Sub
Public Function Load(sFilePath As String)
Dim oFileHelper As New DelimitedFileEngine(Of clsItem)
Dim oList As New List(Of clsItem)
' Load a CSV file
Try
oList = oFileHelper.ReadFileAsList(sFilePath)
Catch ex As Exception
'RaiseEvent ErrorLoad("")
clsErrorLog.Log(ex)
Finally
End Try
' If the list is empty return nothing
If Not IsNothing(oList) Then
Return oList
Else
Return Nothing
End If
End Function
Public Sub Write(sFilePath As String, oList As List(Of clsTranslatedItem))
Dim oFileHelper As New DelimitedFileEngine(Of clsTranslatedItem)
oFileHelper.WriteFile(sFilePath, oList)
RaiseEvent Ready()
End Sub
Public Event ErrorLoad(ByVal sender As Object, ByVal e As EventArgs)
Public Event ErrorWrite(sMessage As String)
Public Event Ready()
End Class
There is a try-catch in my public sub load which catches any exception and logs it to a text file by calling clsErrorLog.log(ex) which then calls this class and logs the error:
Public Shared Sub Log(ex As Exception)
Try
Dim oBestand As New System.IO.StreamWriter(My.Computer.FileSystem.SpecialDirectories.Desktop & "\ErrorLog.txt", True)
If Not IsNothing(oBestand) Then
oBestand.WriteLine("")
oBestand.WriteLine(My.Computer.Clock.LocalTime.ToString)
oBestand.WriteLine(ex.Message)
oBestand.WriteLine(ex.StackTrace)
oBestand.WriteLine("_________________________________________")
oBestand.Close()
End If
Catch exc As Exception
End Try
End Sub
This works fine, but now I want to inform the user that an error occured, so I was thinking to raise an event called "ErrorLoad" (in clsCSV) and catch this in my BLL. But what can I do then? Add a sub that handles this event, which then raises an event in the BLL, caught by the GUI? or is this a long way to this?
I also want to do this for the other events offcourse. But the whole event system in the layered architecture is a bit confusing.
Anyone who can enlighten me?
Thanks in advance!
Without knowing the implementation details of your UI, I can only give you some general advice.
You need some kind of two directional communication between your GUI and your BLL. For example in WPF this is usually done using INotifyPropertyChanged interface and the event it defines.
So the BLL raises a event and the GUI is listening. The basically only has the task of informing the GUI that it has to check a specific property or function or anything like this from the BLL. The rest is up to the GUI to do so and inform the user.
I wouldn't do that using exceptions. These are there to handle the error path of specific functions. This path is done once your BLL noticed the error and prepared it for the UI handling.
I have a WinForms application raising exceptions from code in an EventHandler (E.G. a Button click subscriber);
I have a try..catch block around the invocation of the ShowDialog of the Form;
The exception does not propagate to the try..catch block, but it just stops at the handler and the Form gets closed.
1) How can I propagate the exception to the block?
2) What is the best practice in these cases?
This is a new VS 2010 AddIn probject with a simple Tools menu entry added by the wizard:
Public Sub Exec(ByVal commandName As String, ByVal executeOption As vsCommandExecOption, ByRef varIn As Object, ByRef varOut As Object, ByRef handled As Boolean) Implements IDTCommandTarget.Exec
handled = False
If executeOption = vsCommandExecOption.vsCommandExecOptionDoDefault Then
If commandName = "MyAddin1.Connect.MyAddin1" Then
Dim form1 = New Form1
Try
form1.ShowDialog()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
handled = True
Exit Sub
End If
End If
End Sub
The only content of the Form is a button with a static handler raising a "New Exception()".
When I click the button, the exception is not caught.
In Windows Forms each event handler needs its own try/catch block, or you can try to use Application.ThreadException although maybe it is not possible in an add-in. See Top-Level Exception Handling In Windows Forms Applications
I am writing a simple program to test out various functions of VB.NET, I will later use this in a much more complex program. The idea is to send a message via the serial port com5. The message will be taken from what is entered in the application's textbox. A background worker (activated when a button labeled "send" is pressed) continuously transmits the message. There is also a label, which does nothing.
Imports System.ComponentModel
Public Class Form1
Dim message
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
message = TextBox1.Text
If BackgroundWorker1.IsBusy = False Then
BackgroundWorker1.RunWorkerAsync()
End If
End Sub
Sub SendSerialData(ByVal data As String)
' Send strings to a serial port.
Try
Using com5 As IO.Ports.SerialPort =
My.Computer.Ports.OpenSerialPort("COM5")
com5.WriteLine(data)
End Using
Catch ioex As System.IO.IOException
TextBox1.Text = ("COM5 Not Found!")
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
While (True)
SendSerialData(message)
End While
End Sub
End Class
Originally, I used Application.DoEvents(), but it was slow and I heard it was a bad programming practice. (This, however, had no errors.) So I rewrote the program using a background worker. Now, the program runs fine while running, but when closed, this pops up:
System.ObjectDisposedException was unhandled Message: An unhandled exception of type 'System.ObjectDisposedException' occurred in
mscorlib.dll Additional information: Safe handle has been closed
I believe this has something to do with the background worker, because if the program is closed and I have not ran the background worker, the error does not appear. I have tried placing a try-catch inside every sub in the program (including changing the exception type for the catch in SendSerialData to be any exception), to no avail. This is my first post in case of issues feel free to comment.
What you need to do is signal to the BackgroundWorker1_DoWork thread that the program is closing so that it can tidy up properly. This is something that the BackgroundWorker class in the .NET framework already knows how to do.
You need to do the following:
Use a BackgroundWorker to run the task
Configure the BackgroundWorker to accept a cancellation request
Change the While loop in the background task to check for cancellation
On exiting the program request cancellation of the background task and then wait for the thread to complete.
NB: The MSDN page on BackgroundWorker has an example that does almost exactly what you want.
I am trying to use the S22.Imap library (https://github.com/smiley22/S22.Imap) to listen for new messages.
I have followed the examples provided, but am in need of help...
According to what I have read, the ImapClient object should sit in the background and listen for new messages (using the IDLE feature) and raise an event when a new message is received.
And it seems to work... for a while!
I am using Visual Studio 2010 on Windows 7 Ultimate 64-bit.
I have a simple VB.NET Windows Forms project - here is the code:
Imports S22.Imap
Public Class Form1
Private Shared Sub UnhExceptionHandler(sender As Object, e As System.UnhandledExceptionEventArgs)
Console.WriteLine("Unhandled UI Exception: {0}", DirectCast(e.ExceptionObject, Exception).Message)
End Sub
Private Shared Sub ThrExceptionHandler(sender As Object, e As System.Threading.ThreadExceptionEventArgs)
Console.WriteLine("Unhandled Thread Exception: {0}", e.Exception.Message)
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhExceptionHandler
AddHandler System.Windows.Forms.Application.ThreadException, AddressOf ThrExceptionHandler
Try
Dim c As ImapClient = New ImapClient("imap.gmail.com", 993, "john#john-online.co.uk", "XXXXXXXXXXXXXXXX", AuthMethod.Login, True)
' Should ensure IDLE is actually supported by the server
If c.Supports("IDLE") = False Then
Console.WriteLine("Server does not support IMAP IDLE")
Else
' We want to be informed when new messages arrive
AddHandler c.NewMessage, New EventHandler(Of IdleMessageEventArgs)(AddressOf OnNewMessage)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Shared Sub OnNewMessage(sender As Object, e As IdleMessageEventArgs)
Console.WriteLine("A new message arrived. Message has UID: " & Convert.ToString(e.MessageUID))
End Sub
End Class
When I run this, all goes well for a while - I receive new message notifications OK, but after a while, if I disconnect and reconnect my network connection, I get the following message in 'UnhExceptionHandler()':
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
In this code example, I could simply trap the error and restart the ImapCLient connection. But this is just to test the S22.Imap library - I want to use it in an application where many accounts are checked simultaneously, so need I need to be able to trap the error and determine which individual ImapClient object raised it?
Can anyone suggest any possible resolutions?
I made a application in VB.Net. But some users face crash upon startup. That is "A problem caused this program from working correctly" with just one button "Close the program". Since there are lot of things happening when the app loads, is it possible to know what caused the issue?
If the "Application Framework" is enabled in your project's properties, click the "View Application Events" button on the "Application" project properties page. Then add an event handler:
Partial Friend Class MyApplication
Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
' ...
End Sub
End Class
If you are not using the application framework, you should put a try catch block around your entire Main method. However, that will only catch exceptions that occur on the primary thread. If your application is multi-threaded, you can handle exceptions from all threads by creating a method like this:
Public Sub UnhandledExceptionHandler(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
' ...
End Sub
And then attach it to your current domain's UnhandledException event, like this:
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledExceptionHandler
That event handler will then get called for all unhandled exceptions from anywhere in your domain, regardless of the current thread.