Pass the exception from my class to my form - c#

How can I get my exception from my class to show as a windows error ?
This is my class :
public class Editcap
{
private string _newFileName;
public void convertFileToLibpcap(string filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
_newFileName = fileInfo.FullName.Replace(fileInfo.Extension, "_new") + ".pcap";
invokeProcess(WiresharkProcesses.Editcap, string.Format("{2}{0}{2} -F libpcap {2}{1}{2}", fileInfo.FullName, _newFileName, "\""));
deleteFile(filePath);
}
private void deleteFile(string filePath)
{
try
{
File.Delete(filePath);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public string getNewFileName()
{
return _newFileName;
}
}
From my form:
The function creates new wireshark file with different extension and should delete the old file. If it fails to delete, I want to show the message error in pop up window
Editcap editpcap = new Editcap();
editpcap.convertFileToLibpcap(file.FullName);

You don't need to do anything, the exception will bubble up all on it's own; it's how they work.
Just add a Try/Catch around your calling code:
try
{
Editcap editpcap = new Editcap();
editpcap.convertFileToLibpcap(file.FullName);
}
catch(Exception e)
{
MessageBox.Show("There was an error deleting the file.");
}
Note that there is no need (and in fact some harm) to catching and then re-throwing a new exception in your deleteFile method. You're changing the type of the exception from the more specific and informative IOException to the less expressive Exception, and you're also taking out a lot of the stack trace information. It would be better to just remove that try/catch entirely from deleteFile. It also means you can change the calling code to catch IOException instead of the global Exception. By doing this you can potentially have different catch blocks for different exceptions, allowing you to treat them differently (perhaps crash with one type, log an error for a different one, show a message to the user for something else, etc.).

Related

Any workaround to get outer exceptions from an exception thrown inside an Invoked method in WinForms?

In Windows Forms when an exception is thrown from a call to Control.Invoke or Control.BeginInvoke and it is unhandled by any catch block, it can be handled by a control- or application-level handler via the Windows.Forms.Application.ThreadException event. Its handler takes an EventArgs with a property Exception, which is the exception thrown. However, under the hood, Windows.Forms.Control (undesirably) strips off all but the most inner exception, per this answer.
Found this blog post on it as well, but it doesn't suggest any workaround.
(This currently is causing me to get a trivial stack trace in my error logs--a stack trace that tells me the innermost details of , but there is no calling code mentioned and no way to figure out the code location of such an error.)
Is there a workaround? Is there any way to get all the outer exceptions in my application event handler (which is logging unexpected exceptions for troubleshooting)?
The only suggestion I have found seems to be to catch the exception inside the invoked code and stuff some of its info into Exception.Data, perhaps in a new exception--but if I knew the outer code that caused the exception, I could just fix the bug rather than logging it. Instead, how could I do this globally without wrapping a try-catch around every candidate block of code?
This is admittedly a hack, but it's the best solution I was able to come up with which supports both global exception handling in WinForms and all exceptions, even with inner exceptions.
In the Program.cs:
internal static class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
Application.ThreadException += Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException, true);
Application.Run(new MyMainForm());
}
private static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
_outermostExceptionCache.AddException(e.Exception);
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
Exception exception = null;
if (e?.Exception != null)
exception = _outermostExceptionCache.GetOutermostException(e.Exception);
// Handle exception
}
private static OutermostExceptionCache _outermostExceptionCache = new();
}
And for that you'll need the OutermostExceptionCache class:
public class OutermostExceptionCache
{
public void AddException(Exception ex)
{
if ((ex != null) && (ex is not TargetInvocationException))
{
Exception innermostException = GetInnermostException(ex);
lock (_syncRoot)
{
RemoveOldEntries();
_cache[innermostException] = new CacheEntry(ex);
}
}
}
public Exception GetOutermostException(Exception ex)
{
Exception innermostException = GetInnermostException(ex);
Exception outermostException = null;
lock (_syncRoot)
{
if (_cache.TryGetValue(innermostException, out CacheEntry entry))
{
outermostException = entry.Exception;
_cache.Remove(innermostException);
}
else
{
outermostException = ex;
}
}
return outermostException;
}
private void RemoveOldEntries()
{
DateTime now = DateTime.Now;
foreach (KeyValuePair<Exception, CacheEntry> pair in _cache)
{
TimeSpan timeSinceAdded = now - pair.Value.AddedTime;
if (timeSinceAdded.TotalMinutes > 3)
_cache.Remove(pair.Key);
}
}
private Exception GetInnermostException(Exception ex)
{
return ex.GetBaseException() ?? ex;
}
private readonly object _syncRoot = new();
private readonly Dictionary<Exception, CacheEntry> _cache = new();
private class CacheEntry
{
public CacheEntry(Exception ex)
{
Exception = ex;
AddedTime = DateTime.Now;
}
public Exception Exception { get; }
public DateTime AddedTime { get; }
}
}
The way this works is by watching every exception, as it is thrown, before the runtime even bubbles the exception up to the nearest catch block. Each time an exception is thrown, it is added to a cache, indexed by the innermost (i.e. base) exception. Therefore, when an exception is caught and a new exception is thrown, with the original one as its inner exception, the cache is updated with that outer exception. Then, when Application.ThreadException event handler is provided with the unwrapped, innermost, exception, the handler can look up the outermost one from the cache.
Note: Since even locally-caught exceptions will get added to the cache (and therefore never removed via a call to GetOutermostException), it timestamps each one and automatically ditches any that are older than 3 minutes. That's an arbitrary timeout which can be adjusted as needed. If you make the timeout too short, it could cause problems with debugging since it can cause the exception handling to revert to handling only the innermost exception if you pause the process too long in the debugger (after the exception is thrown but before it is handled).

Correct way to pass errors back to the calling code

I have a function called connect like so:
public boolean connnect(){
{
..... connecting codde
if(connectionSuccessfull)
{
return true;
}
else
{
return false;
}
}
This is a very basic form of error handling, I want to upgrade this function to handle errors correctly. Such as not just tell me false there was an error, but be able to say, error, Authentication failed, or Time-out error etc.
This information then needs to be sent back up the line to the Caller so it can know what happened.
What is the correct way to go about doing this?
{EDIT}
In my care its quite probable that an exception will occur I would say 50% of the time.
I have come up with this, does it look partially correct?
namespace MobileWebServices.Exceptions
{
//Timeout
public abstract class TimeOutException : Exception
{
}
public class ConnectingTimeOutException : TimeoutException
{
}
public class DissconnectingTimeOutException : TimeoutException
{
}
//Authetntication
public abstract class AuthenticationException : Exception
{
}
public class BadAuthenticationException : AuthenticationException
{
}
}
Something along the lines of:
public void Connect()
{
try
{
//code here to look-up the connection details
if(!ValidateConnectionDetails(details))
throw new InvalidOperationException("The connection details are not valid.");
//code here to establish the connection
if(SomeTestThatShowsWereNotHappyWithTheConnection())
throw new Exception("The connection is bad, for some reason");
}
catch(SocketException se)
{
//We'd only have this block if a socket exception is possible. We might just allow it to pass on up.
throw; // User now gets the exception we got, exactly.
//We might re-throw the error, but from here so the stack-trace goes to here rather than the innards of this method:
throw se;
//Most usefully we might throw a new exception that contains this as an inner exception:
throw new Exception("Connecting failed", se);
//Or even better, we might throw a more well-defined exception, that relates to this operation more specifically, with or without the inner exception, depending on whether that is likely to be useful:
throw new ConnectionException("Some message, or maybe just a default is defined in the constructor");
//OR:
throw new ConnectionException("Some message, or maybe just a default is defined in the constructor", se);
}
catch(Exception ex)
{
//If we get to an exception ourselves that isn't of a particular type we're expecting, we probably shouldn't catch it at all. We might though want to note the exception before re-throwing it, or throw a more specific connection with this as an inner-exception:
Log(ex);
throw;
}
}
Because you're no longer returning a value to indicate success, you could also now return an object that represents the connection you created:
public ConnectionObject Connect()
{
// Much as above, but returning the object before the end of the `try`.
}
Returning values representing failure should only be done if that failure is both likely to happen, and something you expect the calling code to be able to reasonably react to right at the point of calling. This isn't that likely with code to connect since the calling code could be code that e.g. connects and then does an operation, and the code calling that in turn is where the exception (whether from here or the subsequent operation) should be caught - it's the code that ultimately cares about the failing.
In the latter case, then returning a value indicating the failure makes a lot more sense. Here though, I'd probably still consider an exception, because it can encapsulate more information, be used by coders in the normal way they use other .NET methods, and because the calling code is probably not written thinking "try to get the connection and then if it works..." it's written thinking "get the connection and then..." with the error case being exactly that; an error case. (For comparison, a method like int.TryParse() is to answer the question "does this string represent an integer, and if so what is it?" where the method int.Parse() answers the question "what is the integer in this string?" with there not being an integer being an error condition).
To think of it another way. Are you currently using a web-browser to browse the web, or are you using it to try to browse the web? Your internet connection could die on you, stopping you from continuing to read these answers, but you'd consider that a problem in what you were trying to do.
The normal approach is to throw an exception (perhaps of a user-defined type), and then to catch those exceptions at a higher level.
If for some reason you cannot use exceptions, you could instead write a wrapper class that encompassed an error message (which would be null if no error occurred) and the bool result (which would only be relevant if the error message is null).
However, I would recommend using exceptions. (The only issue might be whether or not you need to globalise the error message string in the exception, but the consensus is that you should not.)
Here is a sample on how things should be done :
First use your connect() method to return an object (like a Socket for example).
Return a null one if it fails connecting without throwing an Exception.
In your connect() method try/catch your connecting instructions, and rethrow those catched.
Then in the calling method, catch all the Exceptions that can be thrown, and check if the returned object is null or not.
Here is an example of code using Sockets :
public static Socket connect()
{
Socket s = null;
try
{
IPEndPoint iEP = new IPEndPoint("127.0.0.1", 8080);
s = new Socket(iEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
s.Connect(iEP);
if(!s.Connected)
{
return null;
}
}
catch(Exception e)
{
throw e;// Rethrow the Exception to the caller
}
return s;
}
public static void Main(String[] args)
{
Socket mySocket = null;
try
{
mySocket = connect();
}
catch(SocketException e)
{
// TODO - Detailed error about a SocketException
Console.Error.WriteLine("SocketException: " + e.Message + "(" + e.ErrorCode + ")");
}
catch(SecurityException e)
{
// TODO - Detailed error about a SecurityException
Console.Error.WriteLine("SecurityException: " + e.Message);
}
catch(Exception e)
{
// TODO - Detailed error about those Exceptions :
// ArgumentNullException, ObjectDisposedException and InvalidOperationException
Console.Error.WriteLine(e.GetType() + ": " + e.Message);
}
if(mySocket == null)
{
// TODO - Error while initializing the Socket
Console.Error.WriteLine("Error while initializing the Socket");
}
// TODO - Use your Socket here
}
I think the best way is using the try catch exception surrounding your call with the exception you want :
catch(TimeoutException ex)
{
//Do something
}
catch(SqlException ex)
{
//do something
}
//....
catch(Exception ex)
{
//do something
}
Make sure of the order of your catch ( the global Exception in last)

Catching Exception message from Boolean method

I have seen similar questions, but not exactly this:
I would like to know the right way of determining whether a method is executed correctly or not, returning a boolean, and if the method is not executed know the reason, even if an exception is thrown.
I do it in this way, but I think that return inside the catch is a bad practice, so which is the right way?:
if(!myObject.DoSomething('A', out result))
{
MessageBox.Show(myObject.ErrorMessage);
[...]
}else{
MessageBox.Show(result);
[...]
}
class myObject()
{
public string ErrorMessage;
bool DoSomething(char inputValue, out string result)
{
try
{
if(inputValue == 'A')
{
ErrorMessage = "Bad input value: " + inputValue;
return false;
}
[...]
return true;
}catch(Exception ex){
ErrorMessage = ex.Message;
return false;
}
}
I don't like trhow the exception inside the catch because I lose the control of the application (and I can't get the description), and the exception always finish in the form. And if I show the exception in the form, I don't need try catch in the rest of the classes.
I mean that try {} catch(Exception ex) { throw ex;} is the same as not putting try catch.
thanks a lot
My suggestion would be to create your own Exception type (possibly global), and pass it in as a reference.
Thereafter you can still get back your boolean indicating success or failure (and having only one return outside of the try..catch).
public class CustomException
{
private string _message;
private string _title;
public CustomException()
{
_title = "";
_message = "";
}
public CustomException(string title, string message)
{
_title = title;
_message = message;
}
}
Then call DoSomething passing in an instance of CustomException (ce in this case).
CustomException ce = new CustomException();
Be advised this is the best process to solve the problem of having to return a boolean indicating success or failure and know the message, for example; dumping it to a log file or logging to database (particularly for Service Calls - WCF)
However this is not a solution for bad logic in handling business process.
Return false inside a catch isn't by itself bad practice. It's useful when you handle a piece of code's exceptions and it must not fail.
For example, I'm working on a printer piloting DLL at the time, and this DLL must read a XML file containing multiple records to print. The method must not fail because one record fails to print, but it still can return exception if the XML file is not correctly formated.
public void Print(string xmlFile)
{
if (String.IsNullOrWhiteSpace(xmlFile))
throw new ArgumentNullException("No xml file has been passed to the Print method.");
// This line will most likely throw an exception if the XMl file is not well formated
XDocument dom = XDocument.Load(xmlFile);
foreach (XElement n in dom.XPathSelectElements("//RECORDS/RECORD"))
{
try
{
// send commands to the printer, if the printer fails to print, throw a PrinterRecordException
}
catch (PrinterRecordException e)
{
// log print failure, but keep on printing the rest
continue;
}
catch (Exception e)
{
// dunno what happened, but still have to print the rest
continue;
}
}
}
In this example, my function could return false instead of throwing exceptions to the main program, if this program doesn't care. In my case it does :p In my opinion, that's how you should think your method.
Exception handling methods and best practices are a some-what subjective matter. I cannot attest to the method I'm about to present because I have only just started to use it in my own project.
What I suggest is having a static ExceptionHandler class with which you can register any exception to be handled by Generic Parameter and its corresponding handler. This will decouple your business logic from your UI in case you wanted to display some kind of message box when a particular exception occurs.
Here's an example:
/// the real implementation uses lambda's and/or implementations of IExceptionHandler<TException>
ExceptionHandler.Register<InvalidPasswordException>(() => /*some handler logic*/);
// ... else where in the code ...
catch (InvalidPasswordException ex)
{
// do resource clean-up and raise exception for listeners such as the UI or logging infrastructure.
ExceptionHandler.Raise(ex);
}
So far this looks promising, especially when compared with my previous approaches. But only time will tell.
Update
The ExceptionHandler class itself need not be static, for example you might want to have different instances of ExceptionHandlers at different layers of your application if you are using a layered architecture.

ApplicationException throws unhandled exception in VS 2010

This comes from a book but won't debug with correct message in my Visual Studio 2010, it just gives me Unhandled exception at throw new ApplicationException("Smth. bad happened", e);
Is there an error in the book or is it my VS2010 exception settings maybe? The console output is supposed to show that given the file does not exist the inner and outer trace will be printed along with File Not Found. Does it have to do with Just-in-time debugging?
Current Output:Unhandled Exception.........................................................
Desired output:http://www.introprogramming.info/wp-content/uploads/2013/07/clip_image008.png
class program
{
static void Main()
{
try
{
string fileName = "WrongFileName.txt";
ReadFile(fileName);
}
catch (Exception e)
{
throw new ApplicationException("Smth. bad happened", e);
}
}
static void ReadFile(string fileName)
{
TextReader reader = new StreamReader(fileName);
string line = reader.ReadLine();
Console.WriteLine(line);
reader.Close();
}
}
If you want to wrap an exception in your own and have it bubble up, you should remove the inner try, since every try needs a matching catch. Since you're wrapping an exception of your own with the original exception, it doesn't serve any purpose if you are immediately catching it.
try
{
string fileName = "WrongFileName.txt";
ReadFile(fileName);
}
catch (Exception e)
{
throw new ApplicationException("Smth. bad happened", e);
}
EDIT:
This is expected behavior. You're explicitly throwing an exception, and no one is handling it. The book is likely trying to make the point that you can wrap exceptions to provide additional information, while still preserving the original exception. Check to ensure that the file you're trying to open is in the right place.
As an additional note, you should really wrap the file stream in a using block to ensure that the underlying handles/resources are closed.
static void ReadFile(string fileName)
{
using (TextReader reader = new StreamReader(fileName))
{
string line = reader.ReadLine();
Console.WriteLine(line);
reader.Close();
}
}
You have to make sure that you the file "WrongFileName.txt" is in your project's Bin/Debug folder (you include the file in the project and set it's build action to Content and Copy always, if you want it not to throw the exception.
I presume that the book was trying to show, that when the file name is correct, the program will go through normally, but otherwise will cause error.
The catch block gets run because the file doesn't exist in this case and therefore the action inside is executed. This concrete action is to throw the exception again but with more helpful information. You can also see, that this new exception's constructor accepts the original exception as the second parameter, which means it will be included in this exception's InnerException property.

Handling Expected Exceptions

I read several articles regarding good practices in exception handling. Most of it tackled unexpected exceptions yet expected by the author. I just want to clarify and eliminate possible bad practices that I could be doing. Since I already expect these problems to happen already, I assume throwing an exception is a bit redundant.
Let's say I have this code :
string fileName = Path.Combine(Application.StartupPath, "sometextfile.txt");
// There's a possibility that the file doesn't exist <<<<<<<<<<<<<<<<<<<<<
if (!File.Exists(fileName))
{
// Do something here
return;
}
// Therefore, this will return an exception
using (StreamReader file =
new StreamReader(fileName))
{
// Some code here
}
Naturally, what I would do is to inform the user with a MessageBox saying "File not found". Is there an efficient or a better way of doing this?
Another idea that I have is to create an enum which contains expected error codes then create a method which will call a MessageBox showing the error message for that specific situation :
enum ErrorCodes {null, zero, ...}
public void showError(ErrorCodes error)
{
string message;
switch (error)
{
case ErrorCode.null:
{
message = "value cannot be null";
break;
}
case ErrorCode.zero:
{
message = "cannot divide by zero";
break;
}
}
MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
These things are never easy. By definition an exception is (like the Spanish Inquisition) never expected. In your first example the file might exist when you call File.Exist, but then not exist when you try to open it (file deleted, network failed, thumb drive pulled, etc.). As far as a best practice: protect yourself where you can, catch only the exceptions you know how to handle and hope for the best. Programs will fail and the very best thing you can do is make sure that unhandled failures are communicated as clearly as possible to the user of the code (the heart of your second example).
Communicating a failure depends greatly on the what the code does and who is using it. MessageBoxes are often used but generally not 'useful', because if the cause of the error isn't clear to the user about the only thing they can do is send you a jpg image (that's a best case :-D). Providing a way to log problems and/or a custom dialog that allows users to cut/paste information (like a stack trace) is much more useful. Think about the case where a user selects a file and there is a network hiccup. They tell you they got this error about the file not being found, but when you or they look it's there because the network is working correctly by that time. A simple "file not found" message does give you enough information and so you have to tell the user "I don't know, glad it works now" ... this does not inspire confidence. Best practice here is to leave yourself enough 'breadcrumbs' to at least have a rough idea about what has happened. Even something like having a full file path can give you the clues you need to figure out what went wrong.
If the code that is trying to access the file is on the front end, for example an event handler for an on-click, then it's OK to check for the error situation, display a message and return.
If I understand your question correctly you want to know whether you should do this:
public void button_Click() {
if(!File.Exists(textBox.Text)) {
MessageBox.Show("Could not find the file");
return;
}
ProcessFile(textBox.Text); // would have thrown an exception if the file didn't exist
}
That would be fine, except if ProcessFile throws any other kind of Exception it won't be handled.
You could do this:
public void button_Click() {
try {
ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
} catch(Exception ex) {
MessageBox.Show(GetUserMessage(ex));
return;
}
}
In my opinion it's better to do both:
public void button_Click() {
try {
if(!File.Exists(textBox.Text)) {
MessageBox.Show("Could not find the file");
return;
}
ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
} catch(Exception ex) {
MessageBox.Show(GetUserMessage(ex));
return;
}
}
This way you can provide the most specific message to the user relevant to what he was doing at this point. For example if he was trying to open an Excel file you could say "Could not find the Excel file you wanted to import".
This also works in case the file was deleted or renamed between the point you checked and the point you tried to process the file.
Alternatively you could accomplish something similar with this:
public void button_Click() {
try {
if(!File.Exists(textBox.Text)) {
throw new UserException("Could not find the file");
}
ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
} catch(Exception ex) {
MessageBox.Show(GetUserMessage(ex));
return;
}
}
In this case you would create your own Exception class UserException and just pass that message along without translating it. This would allow you to reuse the same code you use to display a message.
Exceptions in Classes
If the error occurs in some class library then you should throw an exception. The purpose of an exception is that an error can't go unnoticed.
For example you shouldn't want this:
class MyFileHandler {
public void OpenFile(string fileName) {
if(!File.Exists(fileName)) return;
// do stuff
}
public void DoStuff() {
// do stuff
}
}
Now if a developer called myFileHandlerInstance.OpenFile("note.txt") he would assumed it worked. You could return a boolean, like so:
class MyFileHandler {
public bool OpenFile(string fileName) {
if(!File.Exists(fileName)) return false;
// do stuff
return true;
}
public void DoStuff() {
// do stuff
}
}
But now you are relying on the developer checking that value, this used to be a common method but errors got ignored and overlooked which is why Exceptions became better practice.
As far as what to display to the user, you really shouldn't display the Exception message directly, those messages are intended for developers not users. I suggest a method that takes an exception object and returns the best message, like so:
public string GetUserErrorMessage(Exception ex) {
if(ex is FileLoadException) {
var fileLoadException = (FileLoadException)ex;
return "Sorry but we failed to load the file: " + fileLoadException.FileName;
}
}
You can inspect the Exception properties for details including error codes if you like. Also I suggest capturing the actual exception details somewhere for your own debugging purposes, somewhere where it's not visible to the user.

Categories

Resources