How to log unhandled exceptions in a vb.net class library project? - vb.net

I'm creating an add-in for Solidworks EPDM (example from API help). This is a class library (.dll) project which is added to EPDM and allows some custom functions to be added to the program.
I want to add logging for unhandled errors so that when an exception is caused by my add-in (as opposed to by the Solidworks EPDM program itself) I can be notified of it and try to fix it.
I'm quite new to all of this (and by all of this I mean VB.NET as a language, programming anything other than macros in VBA, structured exception handling, error logging, etc) and I'm trying to follow MSDN How To: Log Exceptions in Visual Basic but the instructions for logging unhanlded exceptions don't seem applicable to class library projects.
Specifically, I don't know how to get past step 3:
To log an unhandled exception
1. Have a project selected in Solution Explorer. On the Project menu, choose Properties.
2. Click the Application tab.
3. Click the View Application Events button to open the Code Editor.
This opens the ApplicationEvents.vb file.
The View Application Events button is greyed out for class library projects.
So, is there another way to add logging for unhandled exceptions in class library projects? Or, another way to access the ApplicationEvents.vb file for class library objects? I've tried searching for either, and have yet to find a solution that would allow me to log unhandled exceptions.

This is a very basic example but wrap your code with Try/Catch in the only two interface methods (host "callbacks") that IEdmAddIn5 defines and which your add-in class must implement.
Public Sub GetAddInInfo(ByRef poInfo As EdmAddInInfo, ByVal poVault As IEdmVault5, ByVal poCmdMgr As IEdmCmdMgr5) Implements IEdmAddIn5.GetAddInInfo
Try
...
Catch ex As Exception
' Handle exception...
End Try
End Sub
Public Sub OnCmd(ByRef poCmd As EdmCmd, ByRef ppoData As System.Array) Implements IEdmAddIn5.OnCmd
Try
...
Catch ex As Exception
' Handle exception...
End Try
End Sub
I would ordinarily agree with #Hans Passant about re-throwing the exception but I generally have found that to be problematic with an EPDM add-ins as it can cause the COM host to crash.

Related

VB.NET catch error for ENTIRE application

Need help with some VB.net coding (NOT C or c++)
So far I'm using this code to catch errors for specific line(s) of codes:
Try
bla bla bla
Catch ex As Exception
msbox("Error: " & ex.message)
End Try
But sometimes the application stops due to an error where I don't have a catch; how do I on occasions like this call upon a specific Sub (catch the error) for ANY OTHER error in the ENTIRE application where the Sub will display the error message (where I also plan on sending my self an e-mail in that sub to notify me application has stopped)?
I'm not sure if it will conflict with all current Try/Catch commands in my application, but I would prefer to only catch the error on code that currently is not within a Catch handler.
Thank you so much!
This functionality is built into the VB application framework, which is enabled by default in WinForms applications. Open the Application page of the project properties, click the View Application Events button and add a handler for the UnhandledException event using the navigation bar at the top of the code window. Done!
The VB application framework hides some of the complexity of applications that you must implement yourself in C#. It includes a Startup event that you can handle instead of adding code to a Main method, a StartupNextInstance event to support single-instance apps with commandline arguments, multi-threaded splash screen functionality and more.
Regarding your emailing idea, just sure to add in a privacy notice before auto-emailing yourself anything in your apps; this can be a big bone of contention to users, & if an astute one catches it silently phoning home your rep is down the drain.
As for a global error handler, have a look here:
https://www.dotnetcurry.com/patterns-practices/1364/error-handling-dotnet-projects

VB.Net GeckoFX disable dialog errors

While the title might be confusing, I hope this will explain it better.
So, I want to make an VB.Net webbrowser with a GeckoWebBrowser control.
The issue I am facing is that Gecko keeps opening error dialogs even tho I am catching the Error in my code. I just want to disable those dialogs and load an simple html site instead.
Code (Where wbMain is the GeckoWebBrowser control):
Function navigate(ByVal address As String)
Try
wbMain.Navigate(address)
Catch ex As Exception
wbMain.LoadHtml("<h1>An error has occurred!</h1><p>Description: " & ex.Message & "</p>")
End Try
End Function
Gecko keeps doing those errors:
error (I can't post images yet)
But I just want it to display the html page instead of the dialog.
I apologize if I wasn't clear enough or have broken english
I suppose these are the browser alerts, so you need to create your own service which catches these messages.
Create a class which implements the nsIPromptService2 and nsIPrompt prompt interface. In VB syntax is like that I suppose:
class FilteredPromptService Implements nsIPromptService2, nsIPrompt
And then override all the methods required by these interfaces with your own custom logic.

Multiple instances of .NET console app that opens winform throws intermittent access violation

We have a .NET console application that launches a winform (winform is in a .NET dll that is merged into the console exe). It is used as a print router, and launched from a web page.
The main method looks like this:
Sub Main()
Try
Dim pf As PrintForm = New PrintForm()
pf.ShowDialog()
Catch ex As Exception
MsgBox("An error has occured. Please contact your System Administrator.")
End Try
End Sub
We find when multiple instances of the console application are open, (some clients operate in a Citrix environment, where multiple users are logged into the same OS, and even in a normal environment is is not uncommon for users to have several browser tabs open and be printing from multiple tabs which in turn launches multiple instances of the exe), that we intermittently encounter the following error:
Exception Message: Form that is already visible cannot be displayed as
a modal dialog box. Set the form's visible property to false before
calling showDialog.
I can't see why this would be happening, as each instance of the console exe (which is started by a java applet using Runtime.exec), should start in its own instance.
In an effort to get around the above issue I tried changing the code to the following:
<STAThread>
Sub Main()
Try
Dim pf As PrintForm = New PrintForm()
Application.Run(pf)
Catch ex As Exception
MsgBox("An error has occured. Please contact your System Administrator.")
End Try
End Sub
We no longer intermittently get the above error, instead we now intermittently get the following error:
Exception Message: Starting a second message loop on a single thread
is not a valid operation. Use Form.ShowDialog instead.
So it seems I can't win.
Has anyone out there had a similar issue, and if so how did you resolve it?
Or can anyone offer some direction/advise on how to go about solving this one?
This is legacy code, and so I did not design it to use a console application, this is the solution that is already in place. A windows form is something I could try, but I wanted to see if there was a solution that didn't involve rewriting the application. There is a bit more going on than the simple example I gave above to convey the concept of what we are doing.
Thanks for your time.
UPDATE# 1:
Ok so I created a VB.NET WinForms application and moved the copied the forms from the console exe into the WinForms application.
It still has the same problem, except I get less debug info now. I can replicate the issue with a single instance of the application running, but now when the debugger breaks, (I can replicate it when running the exe manually, and when running with VS debugger), I get no disassembly available, and line of source.
The error message is:
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
And the call stack is:
Application: PrintForm.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
at System.Windows.Forms.NativeWindow.DefWndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.ToolTip.WndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.ToolTip+ToolTipNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
at System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32)
at System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
at System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(System.String[])
at PrintForm.My.MyApplication.Main(System.String[])
When I get this error I am alt+tab focus from a PDF viewer that's program window is overlapping the application window, back to the WinForms Application.
It doesn't happen if the PDF viewers window is not overlapping the WinForms Application window.
It is worth mentioning that the icon in the WinForms application that launches the PDF viewer (using the shell) has a tool tip.
Again it is intermittent. But it happens often enough to be a problem.
UPDATE# 2:
I have now replicated it, without even launching the PDF, but just alt+tabing from Windows Explorer back to the Winforms Application and back again... where the Windows Explorer window overlaps the Winforms Application. So all the Winforms Application has done in this scenario is start and become visible.

Universal Exception Handler

Is there a simple way to catch all exceptions in your VB.NET applications? I'm interested in making it so that instead of my users seeing a runtime error, they just are told that an error occurred and to contact tech support, then the relevant error information is logged so our support team can look at it afterwards.
You can use the OnUnhandledException application event to catch (almost) every exception that wasn't handled by the code.
On the Project Properties window (double-click project file on the solution explorer or Project Menu -> [Project name] properties), the Application page has a "View Application Events" button that creates a new file in your project.
In that file there are some events that are fired at application level; one of those is the UnhandledException. Whatever you put there will be executed instead of the classic JIT dialog. The UnhandledExceptionEventArgs object has an Exception property with the unhandled exception object, and a ExitApplication property that decides if the application should exit or continue executing.
Namespace My
' The following events are available for MyApplication:
'
' Startup: Raised when the application starts, before the startup form is created.
' Shutdown: Raised after all application forms are closed. This event is not raised if the application terminates abnormally.
' UnhandledException: Raised if the application encounters an unhandled exception.
' StartupNextInstance: Raised when launching a single-instance application and the application is already active.
' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
Partial Friend Class MyApplication
Private Sub MyApplication_UnhandledException(sender As Object, e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
MessageBox.Show(e.Exception.ToString) '<-- the exception object
e.ExitApplication = True '<-- True if you want the application to close; false to continue - if it can
End Sub
End Class
End Namespace
Note that there are still some "über-exceptions" that can't be caught even with this method (out of memory for example), but this way you can log what exceptions are not being correctly handled on your code, or what scenarios are actualy happening that weren't considered at the beggining.
More info here
As a side note: don't rely too much on this event. This has to be for extremely exceptional cases, as what is caught here should be treated ASAP in the corresponding class/module/method. This is a helpful tool for debugging and test cases but having too much exceptions being handled by this event would be a sign of something wrong in your code.
It depends on what environment your application is running in. If you are using WPF or WinForms, you would launch your application using a main method instead of directly launching a form or page. Your main method should then wrap the calls to instantiate the UI in a try catch block.
So, for a WinForms Application, you could do something like this:
Sub Main
Try
Dim MainUI As New Form1
MainUI.Show()
Application.Run
Catch ex As Exception
'Do that fancy exception processing
End Try
End Sub
You can do something similar with WPF. But, WPF also supports an event model where you are notified of exceptions, very similar to the one that ASP.Net uses.
You will never be able to catch the StackOverflowException.
All the others for sure yes. I'm not familiar with VB, but it is easy to achieve in C#. For VB, I think the generic exeption handler could be
Try
...
Catch e As Exception
...
End Try
Of course this has to wrap all your code. You can find more for examples here.
If you have forms application, it is not practical to have the handler around Application.Run() as the only event handler. Keep it there, but add also two others:
When inside the form, and exception occurs, you want to keep execution in that context – keep the form open etc. For this purpose, use ThreadExceptionEventHandler.
And also, for case when application is irrepairably crashing on some problem, add handler to Dispatcher.UnhandledException event. It is last thing executed before the application ends. You can log the exception to disk for later investigation etc. Very useful.
Let's see some good resource how they are applied.

Visual Basic Customize Unhandled Exceptions

So I have a Visual Basic application created in Visual Studio 2013 and I am trying to find a way to gracefully handle unhandled exceptions. I have graceful failing covered pretty well in the application but want to plan for something I missed.
So, that said. Is there a way to not show a user an unhandled exception directly but rather trigger a function or class that will display a friendly message to the user and write the technical stuff to an error log?
UI frameworks typically have a default handler in their main event loop which raises an event if an exception is thrown inside the loop, but the details vary depending on the framework. If your application is WPF-based, unhandled exceptions on the UI thread will raise Application.DispatcherUnhandledException. If it is WinForms-based, unhandled exceptions on the UI thread will raise Application.ThreadException.
The .Net runtime will raise AppDomain.UnhandledException on exceptions that aren't handled anywhere on the call stack (such as from worker threads).
Assuming Winforms, try this:
On the 'Application' tab of the Project Properties window, click the 'View Application Events' button towards the bottom.
Within the partial class that's generated for you, create a sub like this:
Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
...
end sub
I'll leave the friendly message and logging to you.