I've written an IRC bot in C# using SmartIrc4Net, the purpose of the bot is to just provide information when a command is recognised.
My problem is that, exceptions can happen in the code which causes the application to close but is it possible to keep the application running and not have any "press any key to continue" messages to appear. This should ideally just log the exception and continue on.
I know I could manage the exception in the first place but validating all the input on a per command basis will take a long time. Or there might even be other exceptions I might not have covered.
static void Main(string[] args)
{
IrcClient bot = new IrcClient();
// attach events
try
{
// connect to server, login etc
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
bot.Listen();
// disconnect when Listen() returns our IRC session is over
bot.Disconnect();
}
catch (ConnectionException e)
{
Console.WriteLine("Couldn't connect! Reason: " + e.Message);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(">> Error: " + e);
}
}
Wrap your program in a while(true) block.
static void Main(string[] args)
{
while(true){
IrcClient bot = new IrcClient();
// attach events
try
{
// connect to server, login etc
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
bot.Listen();
// disconnect when Listen() returns our IRC session is over
bot.Disconnect();
}
catch (ConnectionException e)
{
Console.WriteLine("Couldn't connect! Reason: " + e.Message);
}
catch (Exception e)
{
Console.WriteLine(">> Error: " + e);
}
}
}
exceptions can happen in the code which causes the application to
close but is it possible to keep the application running and not have
any "press any key to continue" messages to appear.
Well... yes, you could write your application that way, but I can pretty much guarantee it's not the easy way out you think it is. When an exception is thrown, something has gone wrong. You don't magically fix anything by shrugging your shoulders and carrying on regardless, all that's likely to result from that is that more things will go wrong.
Imagine for a moment you have code that opens a file, and then does something with the contents of that file, and then displays some results to the user. If the file doesn't exist, an exception will be thrown. If you just catch the exception, do nothing, and then carry on with the "do something with the contents of the file" code... congratulations, now you have more exceptions to deal with because there are no contents of the file. You shrug your shoulders again, carry on with the "display the results" code... and congratulations, yet more exceptions because there are no results!
There is no lazy way out. Catch specific exceptions, and handle them appropriately. Yes, this takes more effort. Yes, it takes more code. Yes, you are going to have to think about what "handle it appropriately" means in each individual case. That's programming.
you should try this
static void Main(string[] args)
{
bool shouldStop=false;
while(!shouldStop){
IrcClient bot = new IrcClient();
shouldStop=true;
// attach events
try
{
// connect to server, login etc
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
bot.Listen();
// disconnect when Listen() returns our IRC session is over
bot.Disconnect();
}
catch (ConnectionException e)
{
Console.WriteLine("Couldn't connect! Reason: " + e.Message);
shouldStop=false;
}
catch (Exception e)
{
Console.WriteLine(">> Error: " + e);
shouldStop=false;
}
}
}
Related
I've developed an application used by a third-party company.
Since I'm a horrible coder the application does still have some bugs which causes it to crash (unhandled nullpointerexception for example).
It's a Windows-forms application running on .NET 4.5 and now they are just getting the classic "An unhandled exception caused the app to terminate, press details for more info".
Trying to convince them that pressing "Details" and sending the stack-trace to me is really useful but they all seem reluctant.
Would it be possible to automate this behaviour, like show them a custom global "Exception catcher" where they can just press a button to send it to me by E-mail.
Inbefore "Global exception handling is bad" and "Why does your application throw nullpointerexceptions, you are a bad coder etc."
BR Tomas Anyuru
I guess the exceptions you get are unhandled.
Because of this, you will have to use the Application.ThreadException event to handle them. Because there is no .NET automatic mail sending and message display, you will have to implement your own inside this event.
Please have a look of an answer I wrote to have some examples of Exception catching strategies.
wrap your whole main() function in try-catch statement.
this way any un-handled exception will roll back and will be catched in your catch block:
static void main()
{
try
{
// the application code...
}
catch (Exception ex)
{
DialogResult result = MessageBox.Show(
"Some error occured, please click ok to send it to the develpoer");
if (result = OK)
email(ex); // this is your function to send the email.
// useful information is also in ex.message
// here program will exit without error!
}
}
you can use log 4 net it is open source logging tools, use a lot by Java developer, and this version is specially for .Net http://logging.apache.org/log4net/
In addition to #Shamim code, you can wrap your main function in try, catch block, since the catch block here will track down the exception occurred inside any function called in the try block.
Shooting a mail inside catch block sometime throws and exception about Thread abort, so finally would be the right place to do so :
catch (Exception err)
{
mailBody = "Error: " + Convert.ToString(err.Message) + "<br /> Source: " + Convert.ToString(err.Source);
//Can display some message to user in an Literal Control from here.
}
finally
{
if (!string.IsNullOrEmpty(mailBody))
{
mailObject.To.Add(mailTo);
mailObject.CC.Add(mailCc);
mailObject.Body = mailBody;
MailService(mailObject);
}
}
MailService is a method to send mail which accept a MailObject as parameter.
I wish to prevent "application has stopped working" popup from appearing whenever an exception occurs. One way to do this is obviously calling Environment.Exit(1) in a global exception handler, i.e. AppDomain.CurrentDomain.UnhandledException like this:
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exc = (Exception)e.ExceptionObject;
Console.Error.WriteLine("Exception:\n{0}", exc.Message);
Console.Error.WriteLine("Stack trace:\n{0}", exc.StackTrace);
Environment.Exit(1); // quit silently on exception, don't show the popup
}
However, the above code results in finally blocks not executing due to the order of execution. A simple example of such behavior:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
try
{
Console.WriteLine("try block");
throw new Exception("Somebody set us up the bomb.");
}
catch
{
Console.Error.WriteLine("catch block");
throw;
}
finally
{
Console.WriteLine("finally block");
}
Environment.Exit(1) in the exception handler results in this output (notice no finally block) before application quits:
try block
catch block
Exception:
Somebody set us up the bomb.
Stack trace:
at ...
This can cause serious problems when it is critical that finally block executes, e.g. when cleaning up temp files created inside try.
Is there a simple way around all this? That is, keep global exception handler, customize exception output etc. inside it and and then exit gracefully, but still get finally blocks to execute. I find it weird that this problem has not been mentioned in questions like this.
You are not going to get this. Environment.Exit() ensures that finalizers still run, that could be the fallback. But not for cleaning up temporary files, use the operating system support for that and use the FileOptions.DeleteOnClose option.
In general you should never rely on a hard requirement for cleanup, nothing is getting cleaned-up when the CLR bombs with SOE or FEEE, the user terminates you app from Task Manager, hard-reboots the machine or the power goes off.
I'm trying to handle errors that are passed through 2 dlls I've created. So Console.exe calls dll 1. dll 1 completes an async MQ message read and the handler calls dll 2. If dll 2 errors it passes the Exception (throw) without a problem. But the dll 1 (async) handler catch the throw from dll 2 and give me an unhandled by user message.. I have followed the msdn code to add in the IAsyncResult to keep the hander alive but the issue persists.
can anyone advise on how I should handle this stack and get the handler error returned to the console.exe program so I can present it to the user. Code below:-
Console.exe (snippet)
try
{
_msmq.MSMQ_GetMessage(_msgPath);
//set up the print of the number of queue messages
Console.WriteLine("Main thread: starting a timer");
Timer t = new Timer(ComputeBoundOp, _msgPath, 0, 2000);
Console.Write("Press any key to continue . . .");
Console.ReadKey(true);
t.Dispose(); // Cancel the timer now
}
catch (MessageQueueException _msgQex)
{
Console.WriteLine("An error occurred with the queue:- " + _msgQex);
}
catch (Exception _ex)
{
Console.WriteLine("An error occurred with the queue:- " + _ex);
}
dll 1
public void MSMQ_GetMessage(string _MQ_Path)
{
try
{
//set the correct message queue
MessageQueue _msgQ = new MessageQueue(_MQ_Path, QueueAccessMode.ReceiveAndAdmin);
//set the format of the message queue
_msgQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(_TwitterStreamFeed) });
_msgQ.ReceiveCompleted += new ReceiveCompletedEventHandler(_msgQ_RecieveCompleted);
IAsyncResult _result = _msgQ.BeginReceive();
_asyncList.Add(_result); // asyncList is a global variable of type System.Collections - > this allows the callback to remain open and therefore nit garbage collected while the async thread runs off on it's own
}
catch (Exception _ex)
{
throw new Exception("_msgQ_get Message threw the following error :- " + _ex);
}
}
//method to process message
public void _msgQ_RecieveCompleted(object sender, ReceiveCompletedEventArgs e)
{
try
{
//queue that have received a message
MessageQueue _mq = (MessageQueue)sender;
//get the messge off the queue
Message _mqmsg = _mq.EndReceive(e.AsyncResult);
//set the values back into a formatted struct
//now process your SQL....
Azure_SQL _azuresql = new Azure_SQL();
_azuresql.writeMessageToStorage((_TwitterStreamFeed)_mqmsg.Body);
//refresh queue just in case any changes occurred (optional)
_mq.Refresh();
//tell MessageQueue to receive next message when it arrives
_mq.BeginReceive();
}
catch (Exception _ex)
{
throw;
}
dll 2
public void writeMessageToStorage(_TwitterStreamFeed _msmq_message_as_TSF)
{
try
{
// now do something with the class - i..e write the values to the database
SqlConnection _azurecon = new SqlConnection(_AzuzeSQLConnection);
SqlCommand _sqlcmd = new SqlCommand();
//Setup the command string to call the stored procedure
//Add the parameter to the parameters collection of the command
blah blah blah......... Do SQL writing to Db
_azurecon.Open();
SqlDataReader _sqldr_tweet_place = _sqlcmd_place.ExecuteReader(CommandBehavior.CloseConnection);
}
//now close things off
_azurecon.Close();
}
catch (Exception _ex)
{
// Throw the error to preserve the original
throw;
}
The reason for this is that, internally, the MessageQueue class is explicitly swallowing the exception. Where the MessageQueue class raises the ReceiveCompleted event, it's inside of a try-catch statement - and the catch block is empty. Suffice it to say, if an exception occurs inside your ReceiveCompleted event handler, _msgQ_RecieveCompleted(), nothing's ever going to know it happened.
I see a couple of options, in order of preference.
Option 1 - Shift where the asynchronous call is made
Since this exception-swallowing behavior only occurs when using BeginReceive(), in MSMQ_GetMessage(), you can switch from using BeginReceive() to just Receive(). Then, make your call to MSMQ_GetMessage() asynchronous and any exception that gets thrown will be propagated as expected.
As a side note, a new(er) alternative for making asynchronous calls is available; the Task<> class. As opposed to the Thread class, Task<> has exception handling functionality built in. It does, however, require Framework 4 or higher. There is a good explanation of it's use described in the answer here.
Option 2 - Use a custom event
If refactoring the asynchronous call isn't an option, you can create a custom event in your class in 'dll 2' and subscribe to that event in 'Console.exe'. So when an exception occurs in _msgQ_RecieveCompleted(), you can raise the event and 'Console.exe' will be notified.
The MessageQueue.BeginReceive() method uses the standard .NET APM (Asynchronous Programming Model) pattern. It is very important to understand how it works to know how to properly deal with exceptions. Be sure to read the MSDN article, there are lots of other googable resources available.
In APM, the callback that tells you that a message was received in executed on a thread-pool thread. Which is a very efficient way to get code to run quickly. It is however also a very troublesome way when something goes wrong. The EndReceive() method call is likely to throw an exception, it does so to tell you that the receive operation could not be completed. A standard exception it will throw is ObjectDisposedException. Which will happen when the MessageQueue object gets disposed. In your case when your program terminates. You need to catch that exception and exit from your event handler, it is an expected exception and signals that nothing more useful is going to happen next since the queue was closed.
Then there's a raft of possible exceptions that can be raised by major mishaps in the message queue plumbing. Plus whatever you do with the message. Looks like you execute some Azure code, plenty of ways that can fall over. If you let such an exception escape from the callback method, like you do, then there's no catch clause anywhere in the call stack that is going to handle the exception. The standard way .NET deals with unhandled exceptions is to raise the AppDomain.UnhandledException event and terminate your program. If you didn't actually implement that event then there's nothing decent to look at to diagnose the reason your program ended, the Windows Error Reporting dialog has no good diagnostic.
Whether or not you should try to handle the exception and prevent the program from terminating is up to you. But it pretty strongly fits the "don't shoot the messenger" pattern, it is very unlikely your program can meaningfully continue to execute when such an exception is raised. It invariably takes a human to fix the problem, like restoring the network connection or fixing the message queue. If you do catch it then the odds that the same exception is raised over and over again is fairly likely. After all, there wasn't anything decent you could do in your code to repair the network.
So the best guidance here is to not try, just make sure that IT staff has a good diagnostic so they can repair the problem. Do implement the AppDomain.UnhandledException and display and log the e.UnhandledException.ToString() value. This will also let you learn the number of ways that your program can fail. There might be some conditions that are common enough to warrant catching, something like a temporary network outage. At that point you'll also know what to do about it, in other words what kind of code to write in the catch clause. There is no possible way you know what to write right now, you should therefore not try.
Last but not least, do note that you got yourself into this pickle because you used BeginReceive() unnecessarily. You've already got a perfectly good thread to do work on. But it doesn't do anything useful, it is stuck in the Console.ReadKey() method. Particularly in .NET 4.5 a very tricky method to call, it prevents other threads from writing anything to the console. So your error reporting won't work, it will deadlock when it tries to use Console.WriteLine() to write a diagnostic.
You might as well use MessageQueue.Read() instead. Now dealing with exceptions is a lot easier since they occur on the same thread. The MessageQueue.SynchronizingObject can also be helpful to get completion callbacks to occur on the main thread, but that only works in a GUI app, not in a console app.
I'm working on an existing C# program that queries and makes changes to various resources outside of the program and computer that the program is run on. The program works on most computers but randomly fails on random computers every so often. When this happens we have no feedback as to why other than what the user tells us about the exception that was thrown up on the screen that they may or may not have already cleared. Even if they leave it up on the screen for us it provides little to no useful information to us. I have since modified the program to log particular events and gathered information to a text file that I can use to approximate where the program stopped. This is at least a start but from reading many threads on stackoverflow.com as well as other forums I know that the program needs to at least make an attempt to handle the specific exceptions that could come up when querying and modifying LDAP, DS, DNS, SQL and so on.
Currently there is just big try blocks surrounding all of the to do code with just one catch block at the end of each.
private void method_name()
{
try
{
//many lines of to do code calling many other methods
}
catch (exception ex)
{
MessageBox.Show("An Error has occurred in method_name() :" + ex.Message);
}
My first thought was to nest more specific try/catch blocks within the larger try blocks but I keep running into problems with variables becoming unreachable in different contexts. for example
try
{
LdapConnection ldapConn = new LdapConnection();
ldapConn.Connect(details of connection);
ldapConn.Bind(details of bind statement);
LdapSearchQueue queue = ldapConn.Search(search criteria and such);
LdapMessage message;
}
catch (somesortofexception ex)
{
//do something sensible about it
}
while ((message = queue.getResponse()) != null)
{
//do things with message
}
ldapConn.Disconnect();
the problem being that message and queue are unreachable outside of the try block. This is just one example of something done withing the "//many lines of to do code calling many other methods" that I'm trying to work with.
So here are my questions:
Would it be better to try and make the try block bigger in the above example to include the while loop and ldap disconnect or to just leave the big try loop, make a list of things that happen during that and create many catch blocks at the end to catch specific exceptions? I feel like putting in the smaller try blocks around specific code is the way to go based on what I've read on this site.
Should I use the smaller try blocks like I've been trying to implement, would be be okay to just use a catch block that catches any exception raised within that small snippet of code and log it to my log file or should I try and catch specific exceptions? I don't really have anything different I can do with those exceptions other than log them to the file anyways.
Do I need to throw the exceptions? I don't really want anything bubbling up to the user other than a message in plain english saying that something went wrong and to contact IT. Currently none of the catch blocks throw anything.
About breaking down exceptions, I would always separate the connection code from the query one.
So this would become:
LdapConnection ldapConn = new LdapConnection();
try
{
ldapConn.Connect(details of connection);
ldapConn.Bind(details of bind statement);
}
catch (somesortofexception ex)
{
//Log, send error message..
ldapConn = null;
}
if (ldapConn != null)
{
try
{
//Do what you need with your connection
}
catch (Exception ex)
{
//Log, Error....
}
finally
{
//Disconnect your ldap here
}
}
Ideally i would put all the connection code and search code in separate methods as well,
so you'll have some nicer stack trace.
About error message I would also just use some generic message and log exception specifics into some kind of file ( http://logging.apache.org/log4net/ ) is quite nice for having nicely formatted log files.
A local catch block that swallows a specific exception is fine as long as you're expecting that exception and it can be handled locally. In this case you can provide information to the user based only on what the exception contains, or you can move the variable definitions above the try block if you want to include their state in the logging and/or message.
For exceptions that you're not expecting, you should let them bubble upwards to the top of the call stack where they can be logged by a global handler before exiting the program gracefully. You don't want to potentially nail the corpse in an upright position by swallowing these exceptions.
Assuming this is a WinForms app, the setup of global handlers looks something like this:
public static void Main(string[] args)
{
// Switch-off the Windows Forms default handler for unhandled exceptions.
// NB From .NET 4 upwards, this won't work if the process state is corrupted.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Setup event handler to intercept an unhandled exception on a UI thread.
// NB The exception will still terminate the application.
// But you can show a MessageBox and/or log the exception.
Application.ThreadException +=
new ThreadExceptionEventHandler(App_UiThreadException);
// Setup event handler to intercept unhandled exception on a non-UI thread.
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(App_NonUiThreadException);
// Run the application (open main form etc).
}
I have a windows Service with a main method that includes 5 tasks:
4 System.Timers.Timer()
1 method with infinit loop While(true) handled by a separat thread
N.B: before each method execution a description like "Send command starting now ..." is written in .log file
Yesterday when I checked the log, I noted that all 4 timers methods logs into log file and execute the code, but the method with the infinite loop While(true) logged nothing.
Could you provide me your suggestion about what can cause the infinite loop?
private void StartThread(){
if (_Thread != null){
if (_Thread.IsAlive){
return;
}
}
Log.Write("thread started.");
_Thread = new Thread(SchedulerWorker);
_Thread.IsBackground = true;
_Thread.Name = "scheduler thread";
_Thread.Priority = ThreadPriority.Lowest;
_Thread.Start();
}
private void SchedulerWorker(){
while (true){
try{
DoScheduleWork();
}
catch (Exception ex){
Log.Write("Worker exception : " + ex);
}
Thread.Sleep(TIMER_INTERVAL);
}
}
First, you need to check Log object for multithread support. If it works in main thread does not mean that it works in another thread well at same time. When work with multiple threads you always need to keep in mind about concurrency and other important rules. At least, may be you should place Log into lock statement (I don't know internal structure of your Log object).
Second, don't think that Log not throws exceptions or exceptions don't exists inside catch block. Is quite possible that thread crashes here:
catch (Exception ex)
{
Log.Write("Worker exception : " + ex);
}
Third, try simpliest and safest logging first for your debug purposes. Usually Windows Services logs their events into system journal. But it not well suited for debugging, it is rather a part of Service "interface". Try to use Trace class from System.Diagnostics.
using System.Diagnostics;
...
catch (Exception ex)
{
Trace.WriteLine("Worker exception : " + ex);
}
For multithreaded applications you need more accurately write, verify and debug every step of your code before think that it works as expected. Multithreading in most cases significantly increases the complexity of development.
Creation of Service applications is also not a trivial task. For example using of forms in Services is strongly discouraged and complicates debugging.