So I'm working with cmdlets in C# and using a base cmdlet which derives from PSCmdlet.
Like this: Child <- Parent <- PSCmdlet.
We login to a system using methods in the Parent cmdlet. But sometimes things don't always go right with exceptions, crashes and so on. So it doesn't really logout properly.
My question is as follows:
Is there a method existing that I can implement/override in the Parent cmdlet that will run no matter what happens so that we properly can logout? Kind of like try finally.
I have checked out EndProcessing() and StopProcessing() but they aren't really up to the task in unforeseen situations.
Edit: To clarify, there are multiple cmdlets and the situation is not just about login. There are multiple exceptions that can occur based on code and user-input.
The solution for my problem, as #PetSerAl suggested, was to implement IDisposable in the Parent class.
Using Dispose() I could then add whatever methods needed to finalize the cmdlet no matter what happens.
This sounds like a good case to use Try-catch:
try
{
UserLogin();
OtherMethod();
}
catch(UnauthorizedException au)
{
Console.WriteLine("Unauthorized user... shutting down");
//Closing Code...
Environment.Exit(0);
}
catch(OtherException oe)
{
//Closing Code...
Environment.Exit(0);
}
...
Where you would (if not already) throw the UnauthorizedException() exception within UserLogin() or which ever method you are using to test credentials.
This concept can also be applied to the other areas of code that you are expecting exceptions to be thrown. If the exceptions are because of code not working properly, Try-Catch should not be used to suppress that error as it should be corrected. Exceptions/errors based off of User-Input could be wrapped with Try-Catch.
Related
First of all I am stumped. I have a search-module for a CMS that runs fine on one site, but it won't run as it's supposed to on another site.
I have this code I call both with an Ajax call and simply when loading the search site:
private string GetSearchContent()
{
Query q = GetQuery();
//for each area, set it up, perform search and render result
IArea products = new ProductArea(GetEcomExcludedGroupIDs(), GetEcomLanguage()).Search(q);
IArea pages = new PageArea(GetAreaId())
.Search(q);
IArea news = new NewsArea(GetIncludedNewsCategoryIDs())
.Search(q);
....
}
The important part here is the Search function. This is implemented in the classes, but for some reason the code won't be executed.
I have tried splitting the code up so I am sure that is where the error lies. The freaky part is that it does not throw any exceptions, but it just stops executing whenever I try to call the Search function. It doesn't even enter the function.
The Search function looks like this:
public override IArea Search(Query q)
{
log.Debug("Product search");
....
}
The function it overrides is simply an abstract function on an interface that declares the function.
I have tried copying the function to the same class that are executing it with no luck, and I have tried accessing other functions on the classes, and that worked fine.
My question is then. What could cause this behavior? I have tried looking around but couldn't really find any others with the same problem. And as mentioned before, the exact same code is running smoothly on another site.
I really hope someone can help me get closer to a fix, or at least to understand the problem.
The question is unanswerable as written. You assert that the Search method never runs, and that the faulty line is this one:
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
There are a few different things that could be wrong outside of the Search method:
The NewsArea constructor throws an exception
The GetIncludedNewsCategoryIDs method throws an exception
Either of the above could call into unmanaged code and generate a native Win32 exception, which under some circumstances will simple cause the process to terminate rather than ever returning to managed code.
You state that "there is no try-catch" -- all the more reason to disbelieve your assertion that the method just stops without throwing an exception. Try the following for diagnostic purposes:
try
{
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
}
catch (Exception e)
{
Logger.Log("Caught in the act: " + e.ToString());
throw;
}
If you've run this and still see that the execution stops without logging any exception, then we'll look at other possibilities.
I understand that there are a few ways to exit an application, such as Application.Exit(), Application.ExitThread(), Environment.Exit(), etc.
I have an external "commons" library, and I'm trying to create a generic FailIf method that logs the failure to the logs, does this and that and this and that, then finally exits the application... here's a short version of it.
public static void FailIf(Boolean fail, String message, Int32 exitCode = 1)
{
if (String.IsNullOrEmpty(message))
throw new ArgumentNullException("message");
if (fail)
{
//Do whatever I need to do
//Currently Environment.Exit(exitCode)
Environment.Exit(exitCode);
}
}
I have read that using Environment.Exit isn't the best way to handle things when it comes to WinForm apps, and also when working with WPF apps and Silverlight there are different ways to exit... My question is really:
What do I put to exit gracefully to cover all application types?
Read this about the difference between using Environment and Application :
Application.Exit Vs Environment.Exit
There's an example of what you want to do in the bottom of that page:
if (System.Windows.Forms.Application.MessageLoop)
{
// Use this since we are a WinForms app
System.Windows.Forms.Application.Exit();
}
else
{
// Use this since we are a console app
System.Environment.Exit(1);
}
If it's just an abort, use Environment.Exit(). If it's something very critical (that can't handle any sort of cleanup), use Environment.FailFast().
I would recommend using basic exception handling, so instead of System.Environment.Exit(1) throw new ApplicationException(message) which bubbles up the exception to the main method, in your case something like this:
try{
Application.Run(new MyForm());
}
catch(ApplicationException){
// do custom cleanup/reporting
}
Just make sure you throw the exception from the main thread, else invoke on it before throwing ofcourse
In my services all exposed methods have:
try
{
// the method core is written here
}
catch(Exception ex)
{
Log.Append(ex);
}
It's boring and ugly to repeat it over and over again. Is there any way to avoid that? Is there a better way to keep the service working even if exceptions occur and keep sending the exception details to the Log class?
Try AOP. This is the most widely-used selling point of AOP.
Also, see this discussion here on SO.
You could set up a generic error handling method for all uncaught exceptions like so:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);
Depending on what went wrong, you may not be able to recover from the error... but this should hopefully give you some idea of what what went wrong. If it gets to the point where your application code hasn't handled the exception gracefully, this method could attempt to reinitialize the service to a known working state.
I came up with a semi-solution right now. I can refactor the code:
public TResult ExecuteAndLogOnError(Func<TResult> func)
{
try
{
return func();
}
catch(Exception ex)
{
// logging ...
}
}
And then you can call it on each method:
return ExecuteAndLogOnError(() =>
{
// method core goes here..
});
Which is 4 lines shorter than the original scenario.
In such cases I always use centralized error handlers.
In WCF it is very easy. Some more details:
http://www.haveyougotwoods.com/archive/2009/06/24/creating-a-global-error-handler-in-wcf.aspx
Basically, you just implement the IServiceBehavior interface and then provide your own error handler. That is the best way to do this because you don't have to write any code that handles fatal exceptions (I mean exceptions that you can only log and you don't know what to do about them) in your methods.
If all your doing is logging then just log the error at a later stage... No need to log the error early. If you do more than log the error, well then you're gonna need the try..catch anyway. And if you swallow exceptions (IE. just log them and then go on as if nothings happened) then maybe you're doing it wrong...
I once used something like the Template Function Pattern to resolve a problem like this. I had a base class that did something like:
public void Execute()
{
try
{
ExecuteImplementation();
}
catch (Exception ex)
{
// Log ex
}
}
public abstract void ExecuteImplementation();
There was one derived class per web service operation. The derived classes each implemented ExecuteImplementation.
The web service operations did:
[WebMethod]
public Result WebOperation(Request request)
{
WebOperationClass instance = new WebOperationClass(request);
instance.Execute();
return instance.Result;
}
Exception filters would be good for this. Alas, .NET supports them through MSIL, C++/CLI, VB.NET, but not C#.
If all you're doing in your catch is logging the exception, you could maybe just use a custom error page and let ELMAH log all your uncaught exceptions.
A previous poster brought up AOP (Aspecte-Oriented Programming).
I use PostSharp for basic logging traces/exceptions.
It's quite easy to use and setup.
Check out this link and watch the tutorial.
http://www.sharpcrafters.com/postsharp
--crap it is no longer open source ... anyways you can grab Postsharp1.5 and mess around with it to see if it is something you are interested in it.
I am also in no way affiliated with PostSharp. I'm just a user.
My local test server crashes as soon as I'm trying to write to a logfile. I'm using this for an ASP.NET-Page, codebehind is C#.
Structure:
/
Functions.cs
index.aspx
index.aspx.cs
I create an instance of Functions as my index.aspx loads. In Functions, I define a function for logging, which is called from index.aspx.cs and looks like this:
if (_WriterOpen == false)
{
_Writer = new StreamWriter(_WorkingDir + _Logfile, true);
_WriterOpen = true;
_Writer.AutoFlush = true;
}
_Writer.WriteLine(DateTime.Now.ToString() + ": " + String.Format(Note, Args));
_Writer is defined globally for the Class and contains, as you see, a StreamWriter. The class itself has a destructor to close any connections to the files;
~Functions()
{
_Writer.Flush();
_Writer.Close();
_Writer.Dispose();
}
So, when I open up my page, the logs are written but then the server crashes. So I assume the problem is somewhere in the descructor, but I can't figure out why...
You don't need any destructor, StreamWriter already have it's own.
You should not access other objects from a destructor as it will be called by the Garbage collector, the other objects are in an undeterminable state. You don't know when it will be called and you don't know on which thread it will be called.
NEVER, NEVER, NEVER write a destructor, it's almost always a bad idea.
You may place your cleanup code in the Unload event, see ASP.NET Page Life Cycle.
I'd recommend the using statement which automatically invokes the dispose call. For your purposes the code would look something like:
StreamWriter _Writer;
using(_Writer)
{
if (_WriterOpen == false)
{
_Writer = new StreamWriter(_WorkingDir + _Logfile, true);
_WriterOpen = true;
_Writer.AutoFlush = true;
}
_Writer.WriteLine(DateTime.Now.ToString() + ": " + String.Format(Note, Args));
}
Note I haven't tested this out but it should work (or at least be close). I'll update if needed after checking it out
Also see the following two articles:
Article 1
Article 2
This sounds most likely to be a stack overflow error, caused by a recursive call.
Are you logging an error, that is causing an error, that is logging, causing...etc.
Can you run it in debug mode from Visual Studio?
First: you don't need to call both close and dispose.
See the link from MSDN:
link text
This implementation of Close calls the Dispose method passing a true value.
You must call Close to ensure that all
data is correctly written out to the
underlying stream. Following a call to
Close, any operations on the
StreamWriter might raise exceptions.
If there is insufficient space on the
disk, calling Close will raise an
exception.
If you cant run it through in the debugger, try commenting lines out of Functions until it stops falling over. This should give you a clue.
The garbage collector will call the destructor at some indeterminate time, so if you are getting a regular crash, its probably not the destructor.
I would prefer to make the class inherit from IDisposable and put the clean up code in there. Use the dispose pattern : here
I am currently asking myself some questions about exception handling and eventhandlers, and i hope some of you will give me some help.
I will start to explain what i would like to achieve in my c# application:
I have a top-level method (lets call it the main method). This method calls an asynchronous method (wich is called connect), which connect to a FTP server.
An EventHandler object is associated to this connection, and a "callback" method is called when the connection is successful.
I want to handle exceptions that can be launched during the whole process. So i would like to catch it in the top level method. It works fine for exceptions launched by the connect method (which is called inside the top level method).
However, it does not work for exceptions called inside the "callback" method: the top level method does not catch them and the execution fails.
What can I do to make these exceptions beeing caught by the top level method ? I don't want to handle these exceptions in the callback.
Take a look at how the Backgroundworker deals with this: the Exception is propagated to the Completed event handler.
I assume you have some form of State object that is passed to/from the delegate, that's where you can add such a property. And you will have to catch all exceptions in the thread, at the outermost scope. But 'handling' just means passing it along.
There is a standard pattern for the RunWorkerCompleted event, see this MSDN page.
Consider the below code fragment for wrapping all of your code in a global exception handler:
namespace MyClient
{
class Program
{
static void Main(string[] args)
{
try
{
bool isSuccess = SubMain(string[] args);
}
catch (Exception e)
{
HandleExceptionGracefully(e);
}
}
static bool SubMain(string[] agrs)
{
// Do something
}
static void HandleExceptionGracefully(Exception e)
{
// Display/Send the exception in a graceful manner to the user/admin.
}
}
}
Also, don't forget to make your error handling user-friendly.
There is an event handler in the Application class called ThreadException. This event will be fired whenever an exception is thrown an not caught anywhere in the current call stack.
Edited:
Sorry, I misread the question - I didn't realise that the "main" method in your example isn't the actual main method. In that case you may want to catch the exception inside the callback, but not handle it - instead simply pass it back up to the main method as part of the event args.
The BackgroundWorker in Winforms does something similar.
Thanks for your answers.
It seems that using the BackgroundWorker solve this problem.
I did not try it, because i chose to avoid this implementation burden. So I took away my asynchronous call and made my application behaving synchronously.
One tip for people using the Compact Framework instead of the full .NET Framework:
the BackgroundWorker is not available in CF, but a similar solution is provided by OpenNETCF (see the BackgroundWorker class in the Smart Device Framework).
A more convenient way to deal with this problem of top-level exception handling is to use delegates.
These c# delegates allow to call methods in a asynchronous way. And delegates allow also top-level exception handling. Indeed, exceptions thrown inside delegates are re-thrown on the original thread.
I don't know why i did not think about delegates before.
I hope it will help.
See these nice articles about delegates:
Article 1
Article 2