hresult
hresult

Reputation: 301

Assembly InvokeMember try{} catch()

we're currently working on a program which has an open C# API interface. Now, imagine you have the following C# script:

int[] Test = { 0, 3 };

private void Test()
{
    Debug.Log(Test[4].ToString()); //Exception!!
}

Compiling works, however, if we now try to Invoke the Test Void it will fail. It should obviously fail, but we want to catch the Exception, so our whole Application doesn't freeze.

Assembly assembly = Assembly.LoadFrom("C:/Our/Path/To/Dll.dll");

Type type = assembly.GetType("ClassApplication1.Test");
object instance = Activator.CreateInstance(type);

type.InvokeMember("Test",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreReturn,
null,
instance,
null);

This popup will appear in Visual Studio 2012 if we're debugging, without debugging our Application simply crashes completly.

nn

nn

//Edit:

I know that the Debug.Log(Test[4].ToString()); //Exception!! is wrong and will call an excetpion (!!!). It was wanted. Putting a try {} block through that will work, but keep in mind that the scripts are 3rd-party made. I don't have my hands on this, but atleast I wan't that our application is EATING the errors (and DISPLAYS them in a richTextBox), instead of throwing them (=Application crashes).

TLDR: I want to prevent 3rd party assemblies which i load into my assembly to make my program crash

Upvotes: 0

Views: 1387

Answers (2)

bmm6o
bmm6o

Reputation: 6515

If I understand it, you simply need to catch the exception thrown by InvokeMember:

try
{
    type.InvokeMember("Test", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreReturn, null, instance, null);
}
catch(TargetInvocationException e)
{
    // e.InnerException will be IndexOutOfRangeException in your example
}
catch(Exception e)
{  // one of the other exceptions
}

See MSDN for all of the possible exceptions that can lead to the second block. You probably want to just wrap all of the code (starting from loading the assembly) in a try block, since those can fail also.

You should also investigate AppDomains, they are the "right" way to do isolation like this. They hook into the CLR to provide more protection than you can possibly manage on your own.

Upvotes: 2

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

int[] Test = { 0, 3 };

This line sets Test array size to 2, so the only items you can take from it are:

Test[0] // == 0
Test[1] // == 3

That's why Debug.Log(Test[4].ToString()); throws an exception.

To catch it you have to use try/catch block when calling Test method:

try
{
    Test();
}
catch(IndexOutOfRangeException ex)
{
    Console.WriteLine("Exception caught: {0}", ex.Message);
}

Upvotes: 0

Related Questions