It is a silly question I admit. So, apologies if this wastes your time but I just cannot find out a solution.
A WinForm Application which has a Class Library. I use Log4Net dll for logging information.
On Button_Click, I call a function in the Class Library which might throw an error. So, I have the contents of the function inside a try-catch-finally block. In the catch, I write log statements (using Log4Net dll).
Now, that an error has occurred, I want a Message to be shown to the UI. And after a Message is shown, I want it to quit.
How do I pass the control from the catch block of the Class Library back to the Form code so that I display a message and then quit?
Just call throw without any parameters after you've logged the error in the exception handler in the class library and it'll rethrow the exact same exception with the same callstack etc.
Then let your form catch it and handle it as you want.
In the Class Library Method, in the catch, rethrow the exception, so that it can bubble up to the form.
In the form Button_Click wrap the Class Method call in a try catch, and in the catch display the message and exit.
The library should probably re-throw the exception after logging about it.
class Form
{
OnClick()
{
try
{
library.Routine();
}
catch(Exception e)
{
// messagebox
// exit
}
}
}
class Library
{
public void Routine()
{
try
{
// stuff
}
catch(Exception e)
{
logger.error("error in routine", e);
throw;
}
}
}
Related
Below is my code after got the exception immediately it should trigger one more time for execution but didn't execute.Without try,catch it was executing but after keep the code in try and catch RetryAnalyzer is not working as expected please anyone help me how to implement RetryAnalyzer in try,catch block
#Test(priority=4,enabled=true,retryAnalyzer=RetryAnalyzer.class)
public void TC_04() throws InterruptedException
{
try
{
extent=new
ExtentReports("/Users/anakin/workspace/Reports/MKE.html");
Login_Objects.Switch_PB2U(driver).click();
String screenshot_path = Screenshot.createScreenshot(driver);
String image = log.addScreenCapture(screenshot_path);
log.log(LogStatus.PASS, "To Stocks",image);
extent.endTest(log);
driver.closeApp();
}
catch(Exception e)
{
String screenshot_path = Screenshot.createScreenshot(driver);
String image = log.addScreenCapture(screenshot_path);
log.log(LogStatus.FAIL, "Verify Suggest Stocks ", image);
extent.endTest(log);
}
}
Catching exception in your complete test code is a bad practice. Even as in your case you are capturing screenshot in case of failure, you should use listener than catching exception.
Since retry analyzer works for failed tests, and you are cathing exceptions and thus supressing the errors, it might give the impression that your test never failed and thus the retryAnalyzer is not working.
Solution : Move code in Exception to Listeners and remove unnecessary Exception handling.
I'm using the ABP framework with WinForms and I need to identify the best way to intercept an exception and log this information.
My WinForms is a Multiple-Document Interface (MDI) application. I add a HandleException in Program.cs so that when the application throws an exception, I'm able to log it in the log file. But if I get an exception in an ApplicationService, this exception is handled by ABP and not thrown back to WinForms, and nothing is written in the log file.
Do I need to implement some interface to have the classic logging like MVC/Angular app?
UPDATE
I found that the problem is related to async operation. Usually I call:
await _service.GetProducts();
If an exception is thrown, the main thread does not intercept it. If I switch to:
AsyncHelper.RunSync(() => _service.GetProducts());
Then the main thread intercepts the error.
because the exception is thrown in another thread you have to handle unhandled exceptions of the application domain. insert the exception handler into the starting point of your application. for win forms i guess you can use program.cs
static class Program
{
[STAThread]
static void Main(string[] argv)
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender,e)
=> HandleException(e.ExceptionObject);
Application.ThreadException += (sender,e)
=> HandleException(e.Exception);
Application.Run(new MainWindow());
}
catch (Exception ex)
{
HandleException(ex);
}
}
static void HandleException(object exception) {
var ex= exception as Exception;
if (ex== null) {
ex= new NotSupportedException("Unhandled exception: " + exceptionObject.ToString());
}
//you can log exception here -> ex.ToString();
}
}
Ok after some invastigation and googling I found this MSDN explanation Asynchronous Programming - Async from the Start
Accoriding to this article I change my program start to move to async code.
I need to chage a little bit more because I'm on Mdi Form when open a inside form
Form1 childForm = Globals.Bootstrapper.IocManager.Resolve<Form1>();
childForm.MdiParent = this;
var formAsync = childForm.InitializeAsync();
FormExtension.HandleExceptions(formAsync);
childForm.Show();
I add the static class to intercept the error form Abp
public static async void HandleExceptions(Task task)
{
try
{
await Task.Yield(); //ensure this runs as a continuation
await task;
}
catch (Exception ex)
{
//deal with exception, either with message box
//or delegating to general exception handling logic you may have wired up
//e.g. to Application.ThreadException and AppDomain.UnhandledException
var log = Globals.Bootstrapper.IocManager.IocContainer.Resolve<ILogger>();
LogHelper.LogException(log, ex);
//Exception handling...
MessageBox.Show("Ops!" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
//Application.Exit();
}
}
Now my log file is populated in correct way
I'm building a WPF application using the SimpleMVVM framework and I'm having trouble catching exceptions. I use the MessageBus of SimpleMVVM to send a message to another viewmodel. This all works fine, but I noticed that exceptions raised in the code executed by the messagebus get suppressed. Here's what I've got so far:
My MainWindow contains a button that fires a TempCommand on the MainWindowViewModel. This command in turn calls the Test method (shown below), which sends out a notification message using the MessageBus of SimpleMVVM.
private void Temp()
{
SendMessage("Temp", new NotificationEventArgs());
}
My MainWindow also contains a Frame with content. The ViewModel of this content, CustomerViewModel, has registered to receive these notifications in its constructor:
public CustomerDetailsViewModel(ICustomerServiceAgent agent)
{
RegisterToReceiveMessages("Temp", Temp);
}
Where the Temp method simply throws an exception:
private void Temp(object sender, NotificationEventArgs args)
{
throw new NotImplementedException("Somewhere, something horrible happened");
}
When I debug the application, I clearly see the Temp method being called and the exception being raised. But for some reason, that's all. The application is unaffected and my exception trapping code is unaware of the exception.
I trap exceptions in two ways. The first is by handling the event on the Dispatcher:
<Application x:Class="MyApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException">
Where the code-behind looks like:
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
Log("Exception: " + e.Exception.Message);
e.Handled = true;
}
public static void Log(string message)
{
File.AppendAllText(#"D:\Temp\log.txt", "[" + DateTime.Now.ToString("F") + "] [" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "] " + message + Environment.NewLine);
}
This code catches some exceptions, but not all. I found out that WPF suppresses databinding exceptions by default. Because my ViewModels are bounded through the DataContext property on my view, I thought this was the problem. I found this article, which defines a TraceListener that uses the PresentationTraceSources class. Databinding exceptions now get caught, but... Not the exceptions thrown in the code executed through the MessageBus.
I've created a solution demonstrating this behavior, it can be downloaded here.
And this is where I'm stuck. What am I missing? How do I catch these exceptions?
Big thanks in advance.
JP
I think it is a bug or problem with the implementation of the MessageBus in SimpleMVVM.
Cause multiple subscribers can subscribe to a token, the current implementation ensures that each subscribed method gets called even when one registered method throws an exception. In this case the exception is catched and written out to the Console.
The method that is responsible to call a subscribed method is SafeNotify
private void SafeNotify(Action method, bool post) {
try {
// Fire the event on the UI thread
if (post){
if (Dispatcher.CheckAccess()){
method();
}
else{
Dispatcher.BeginInvoke(method);
}
}
// Fire event on a ThreadPool thread
else{
ThreadPool.QueueUserWorkItem(o => method(), null);
}
}
catch (Exception ex){
// If there's an exception write it to the Output window
Debug.WriteLine(ex.ToString());
}
}
When the method call gets queued in the ThreadPool, you have no chance to handle the thrown exception. See also this post for further information.
The only option you have is to ensure that the code of your own registered methods is always surrounded by a try-catch-block.
In a Winform I get the exception: "Invoke or BeginInvoke cannot be called on a control until the window handle has been created" during an AsyncCallback.
The application works normally on other computers. I was wondering whether there might be a computer or network setting that could be responsible for the exception. The callback is a cross-domain callback, however all data are received and displayed in the Winform, then the exception occurs.
The exception is a fatal exception and the Windows message "App.. has stopped working" appears.
EDIT 1:
public void OpenFormCallback(IAsyncResult ar)
{
// 'this' is a Winform
this.BeginInvoke(new DelegateVoid(SetDataSource));
}
Normally it works, now in the exceptional case there exists a very fast network connection which may be the cause for the fact that a handle is not yet created. Just realised that.
Should I try:
public void OpenFormCallback(IAsyncResult ar)
{
// 'this' is a Winform
while (!this.IsHandleCreated) { }
this.BeginInvoke(new DelegateVoid(SetDataSource));
}
? Risking an eternal loop?
EDIT 2: I tried:
public void OpenFormCallback(IAsyncResult ar)
{
// 'this' is a Winform
if (IsHandleCreated) { CreateHandle() }
this.BeginInvoke(new DelegateVoid(SetDataSource));
}
But the main form is not displayed, it comes in the state "Not responding".
Add checking yourform.IsHandleCreated before calling invoke/BeginInvoke from your callback
Try this:
public void OpenFormCallback(IAsyncResult ar)
{
while (!this.IsHandleCreated) { Application.DoEvents(); }
this.BeginInvoke(new DelegateVoid(SetDataSource));
}
I started a new WPF project in VS2008 and then added some code to trap DispatcherUnhandledException. Then I added a throw exception to Window1
but the error is not trapped by the handler. Why?
public App()
{
this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
System.Windows.MessageBox.Show(string.Format("An error occured: {0}", e.Exception.Message), "Error");
e.Handled = true;
}
void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
throw new NotImplementedException();
}
This can happen because of the way you have the debugger handling exceptions -- Debug/Exceptions... should allow you to configure exactly how you want it handled.
Look at following msdn link http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx
Following is Relevant here
If an exception is not handled on either a background user interface (UI) thread (a thread with its own Dispatcher) or a background worker thread (a thread without a Dispatcher), the exception is not forwarded to the main UI thread. Consequently, DispatcherUnhandledException is not raised. In these circumstances, you will need to write code to do the following:
Handle exceptions on the background thread.
Dispatch those exceptions to the main UI thread.
Rethrow them on the main UI thread without handling them to allow DispatcherUnhandledException to be raised.
This is how I handle it. This isn't pretty but keep in mind that this type of error should never make it past debugging as a dev. Those errors should be long resolved before you go to production (so its okay that this isn't pretty). In the Startup project, in the App.xaml (App.xaml.cs) code behind, I put the following code.
OnStartup, create a DispatcherUnhandledException event handler
In the handler, use a MessageBox to display the message. Note that its likely the startup window has not yet been created so don't try to put it in a window.
e.Handle the error
I like to see when there are additional internal errors so I continue to call the display window until the internal error is null.
I'm not sure why the code block special characters aren't formatting this correctly. Sorry about that.
protected override void OnStartup(StartupEventArgs e)
{
// define application exception handler
Application.Current.DispatcherUnhandledException +=
AppDispatcherUnhandledException;
// defer other startup processing to base class
base.OnStartup(e);
}
private void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
runException(e.Exception);
e.Handled = true;
}
void runException(Exception ex)
{
MessageBox.Show(
String.Format(
"{0} Error: {1}\r\n\r\n{2}",
ex.Source, ex.Message, ex.StackTrace,
"Initialize Error",
MessageBoxButton.OK,
MessageBoxImage.Error));
if (ex.InnerException != null)
{
runException(ex.InnerException);
}
}
At first, even outside the debugging environment, my handler does not seem to be triggering.....then I realized I forget to set e.Handled = true.
In truth it was working but because e.Handled was still false the standard exception handler still kicked in and did its thing.
Once I set e.Handled = true, then everything was hunky dory. So if its not working for you, make sure you've done that step.
For those interested
It seems that the IDE is still breaking on exceptions and that if you click continue in the IDE it call the error handler.