All I want to achieve is to catch exceptions on my app so that I can send them to a server. I figured out that I can do this by writing my custom UncaughtExceptionHandler base on native Android code in Java answered here in StackOverflow.
This is my CustomExceptionHandler class:
public class CustomExceptionHandler : Thread.IUncaughtExceptionHandler
{
public IntPtr Handle { get; private set; }
public CustomExceptionHandler(Thread.IUncaughtExceptionHandler exceptionHandler)
{
Handle = exceptionHandler.Handle;
}
public void UncaughtException(Thread t, Throwable e)
{
// Submit exception details to a server
...
// Display error message for local debugging purposes
Debug.WriteLine(e);
}
public void Dispose()
{
throw new NotImplementedException();
}
}
Then I used this class to set the DefaultUncaughtExceptionHandler in my Activity:
// Set the default exception handler to a custom one
Thread.DefaultUncaughtExceptionHandler = new CustomExceptionHandler(
Thread.DefaultUncaughtExceptionHandler);
I don't know what is wrong with this approach, it did build but I got an InvalidCastException on runtime.
I have the same Thread.IUncaughtExceptionHandler interface types for my CustomExceptionHandler and the DefaultUncaughtExceptionHandler, but why am I getting this error? Please enlighten me. Thank you.
And it strikes again :D This is a common mistake. You have to inherit Java.Lang.Object if you implement Java interfaces.
public class CustomExceptionHandler : Java.Lang.Object, Thread.IUncaughtExceptionHandler
{
public void UncaughtException(Thread t, Throwable e)
{
// Submit exception details to a server
...
// Display error message for local debugging purposes
Debug.WriteLine(e);
}
}
Related
C# Question. Arbitrary class Class has method Foo(), a method which can throw an exception. Is there some way to add a private callback mechanism bar() to Class, such that if Foo() throws an exception, bar() execution will be triggered before the throw keeps going up the chain? If that can't happen, what about after the exception is caught?
-- Edit --
Since some of the initial comments are "this is confusing what are you doing dude" I'll address it further.
The reason I would like an exception listener is because I have some publicly readable boolean state about class Class, which I want to be set to true whenever an exception has been thrown. Since there could be potentially multiple functions within Class which throw exceptions, I don't want to do the boiler plate work of setting hasError to true each time an exception is thrown. Automate, baby.
So our interface, and main function are:
public interface IObjectProvider
{
IEnumerable<object> Allobjects { get; }
}
public interface IContext
{
delegate bool ContextIsStillValid(object o);
delegate void Run(object o);
}
// main program
public static void Main() {
IContext context = initcontext(...);
IObjectProvider objectProvider = initobjectprovider(...);
// ...program executes for awhile...
foreach(var obj in objectProvider.AllObjects)
{
if(context.ContextIsStillValid(obj))
{
try
{
context.Run(obj);
}
catch(Exception e)
{
// log the error
}
}
}
}
In the above code snippet, we specify some IContext which will 'Run' using some object, if and only if that IContext first successfully passes a 'Validation' check using that same object. Fine. Now, a common variation of implementation for IContext is the following (take my word, it is):
public class Class : IContext {
private bool _hasError = false;
// so our validation check is implemented with an internal flag.
// how is it set?
public bool ContextIsStillValid = (o) => !_hasError;
public void Run =
(o) =>
{
string potentially_null_string = getstring(...);
if(potentially_null_string == null)
{
// our internal flag is set upon the need to throw an exception
this._hasError = true;
throw new Exception("string was null at wrong time");
}
Global.DoSomethingWith(potentially_null_string.Split(',');
};
}
Here, we've demonstrated a common implementation of IContext, such that once the Run method throws a single Exception, the Run method should become unreachable due to IsContextStillValid subsequently always returning false.
Now imagine that there are other Exception-throwing calls within our implementation of Run(object). The problem is that every time we want to throw a new exception, we have to duplicate code to the effect of _hasError = true; throw new Exception(...);. Ideally, an exception listener would resolve this issue for us, and I am curious if any of you know how to implement one.
Hope that helps.
public class MyClass
{
public void Foo()
{
try
{
//Execute some code that might fail
}
catch
{
bar();
throw;
}
}
private void bar()
{
//do something before throwing
}
}
I have a C# application that can load other dlls with Activator.CreateInstance(type), that implement a given interface (plugins).
Now I want to catch all exceptions thrown from that new instance in it's own exception handler (because I cannot be sure that every exception is handled by the plugin properly) to present a message like:
Plugin [PluginName] caused the following error: [Exception.Message]
I can subscribe to the AppDomain.CurrentDomain.UnhandledException event, but this catches all exceptions and not only the ones caused by a certain plugin and I also can't see [that the|what] plugin caused the exception.
Is it possible to assign a exception handler to the created instance?
Thanks in advance,
Frank
I'm not sure I understand your exact scenario, but a solution could be creating a wrapper class around the plugin object that takes care of making sure all potential exceptions are handled correctly:
public interface IPluginObject
{
void Foo();
IBlah Bar();
...
}
public Wrapper<T>: IPluginObject where T: IPluginObject
{
private readonly T inner;
public Wrapper(IPlugin obj) { inner = obj; }
public void Foo()
{
try { inner.Foo() }
catch ....
finally ...
}
public IBlah Bar()
{
try { return inner.Bar(); }
catch ...
finally ...
}
}
Cumbersome? Yes, but you do get the benefit of knowing exactly what plugin is being troublesome.
I have a legacy library in my ASP.NET MVC app that raises a lot of exceptions I need to ignore. I ignore these exceptions in Application_Error like this
protected void Application_Error()
{
if (exception is PolicyViolationException)
{
Response.Clear();
Server.ClearError();
}
}
I know this is a code smell, but I can't do much about it at the moment.
Is there a way to stop them even getting to Application_Error?
Use a Wrapper class (the Adapter Pattern). Then, instead of referencing the legacy library, you use the wrapper class. And the wrapper can handle (or ignore) the exceptions as needed.
class Legacy
{ public void DoThis()
{ ... }
public void DoThat()
{ ... }
}
class Wrapper
{ Legacy _legacy;
public Wrapper() { _legacy = new Legacy(); }
public void DoThis()
{
try {
_legacy.DoThis();
}
catch (PolicyViolationException exception) {
//ignore
}
}
...
}
In this example, I would never reference the class Legacy. Instead, I would reference the class Wrapper. Then I don't have to worry about the exceptions because they won't get out of the Wrapper instance if I don't want them to.
Given the following pseudo C# code:
class BigMessage : Message { }
class SmallMessage : Message { }
abstract class Message
{
static public Message Factory()
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
if (randomNumber > 50)
{
return new BigMessage();
}
else
{
return new SmallMessage();
}
}
}
class Worker
{
public void Comprehend(BigMessage bm)
{
}
public void Comprehend(SmallMessage bm)
{
}
public void start() {
Message msg = Message.Factory();
Comprehend(msg);
}
}
If I ask the Factory to give me a random Message object inherited from Message (e.g. Big or Small Message), and I would like the Comprehend methods in the Worker class to act on the type of message given using overloading (the proper OO way, rather than explicit type checking), why do I get the following two types of errors and can you help me understand what I am doing wrong?
The best overloaded method match for 'Worker.Comprehend(BigMessage)' has some invalid arguments.
cannot convert from 'Message' to 'BigMessage'
Ultimately I expect the Factory to provide me with an object inherited from Message, who's type I do not know in advance. I do need to act differently given the different type returned. Inheritance is very helpful in this scenario as the abstract class provides much useful functionality shared with it's child classes.
.NET 4.5 is used.
Thanks in advance!
The reason that you get the conversion error is that you cannot convert a "Message" type to a concrete "BigMessage" or "SmallMessage". It should be the other way around where you have Comprehend(Message msg) and that allows the method to accept any inherited objects.
In addition, what I think you are trying to achieve is polymorphism. I believe to correctly create your objects, your base abstract class Message should have a method called "Comprehend" and in your worker process, you call msg.Comprenhend(). This way, as you get more additional message types, you are not adding additional comprehend methods to your worker class for each message. By leveraging OOP and inheritance, you let the object decide how they comprehend themselves.
sample code below:
abstract class Message
{
abstract void Comprehend();
public static Message Factory(){... code here to return message }
}
class BigMessage : Message
{
public void Comprehend()
{
//do work here
}
}
class SmallMessage : Message
{
public void Comprehend()
{
//do work here
}
class Worker
{
public void Start()
{
var msg = Message.Factory();
msg.Comprehend();
}
}
Hope this helps!
https://github.com/apache/log4net
I am compiling log4net from the source above, but it doesn't pass verification:
[IL]: Error: [log4net.dll : log4net.Plugin.RemoteLoggingServerPlugin::Attach][offset 0x00000029] Method is not visible.
Code is ok:
public interface ILoggerRepository
{
...
}
public interface IPlugin
{
void Attach(ILoggerRepository repository);
}
public abstract class PluginSkeleton : IPlugin
{
public virtual void Attach(ILoggerRepository repository) { }
}
public class RemoteLoggingServerPlugin : PluginSkeleton
{
override public void Attach(ILoggerRepository repository)
{
base.Attach(repository);
...
}
}
https://github.com/apache/log4net/blob/trunk/src/Plugin/IPlugin.cs
https://github.com/apache/log4net/blob/trunk/src/Plugin/PluginSkeleton.cs
https://github.com/apache/log4net/blob/trunk/src/Plugin/RemoteLoggingServerPlugin.cs
Investigation shows that it fails in calling RemotingServices.Marshal():
override public void Attach(ILoggerRepository repository)
{
base.Attach(repository);
// Create the sink and marshal it
m_sink = new RemoteLoggingSinkImpl(repository);
try
{
**RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink));**
}
catch(Exception ex)
{
LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex);
}
}
But there is nothing crucial here. Moreover calling RemotingServices.Marshal() with any type leads to the same problems:
Even if I change the Attach() to this:
override public void Attach(ILoggerRepository repository)
{
RemotingServices.Marshal(null, null, typeof(int));
}
Can someone spot what is the problem?
The problem is related to the fact that with .NET 4 Level 2 transparency was introduced. (See http://msdn.microsoft.com/en-us/library/dd233102.aspx for details.)
The method override public void Attach(ILoggerRepository repository) is lacking the SecuritySafeCriticalAttribute. Adding the attribute:
#if NET_4_0
[System.Security.SecuritySafeCritical]
#endif
override public void Attach(ILoggerRepository repository)
{
// ...
}
will make the IL verification pass. (Also see: http://msdn.microsoft.com/en-us/library/bb397858.aspx for further information.)
Update: To shed some more light on why verification fails (which might not be immediately clear by just reading the articles in the links provided) here is a short explanation.
RemotingServices.Marshal has the [SecuritySafeCritical] attribute applied. So one would assume that calling the method from a transparent method would be allowed. However RemotingServices.Marshal returns an object of type System.Runtime.Remoting.ObjRef and said type is annotated with the [SecurityCritical] attribute. If the log4net code would store a reference to the returned value in a local variable, Code Analysis would detect the error and issue a CA2140 warning ("Transparent code must not reference security critical items").
Now apparently under the security transparency rules, a transparent method may not call a security safe-critical method if the called method returns a security critical type even if the transparent method does not store a reference to the returned object as the following sample demonstrates:
public class TransparencyRulesDemo
{
[SecuritySafeCritical]
public void SafeGetCritical()
{
GetCritical();
}
public void TransparentGetCritical()
{
// Below line will trigger a CA2140 warning if uncommented...
// var critical = GetCritical();
// ...the following line on the other hand will not produce any warning
// but will lead to IL verification errors and MethodAccessExceptions if
// called from transparent code.
GetCritical();
}
[SecuritySafeCritical]
public Critical GetCritical()
{
return new Critical();
}
}
[SecurityCritical]
public class Critical
{
}
This btw. makes the [SecuritySafeCritical] attribute on RemotingServices.Marshal kind of pointless.