Assembly InvokeMember try {} catch()

时间:2013-09-06 18:19:06

标签: c# .net-assembly

我们目前正在开发一个具有开放C#API接口的程序。现在,假设您有以下C#脚本:

int[] Test = { 0, 3 };

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

编译工作,但是,如果我们现在尝试Invoke Test Void它将失败。它应该显然会失败,但我们想要捕获异常,因此我们的整个应用程序不会冻结。

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);

如果我们正在调试,这个弹出窗口将出现在Visual Studio 2012中,而不调试我们的应用程序只是完全崩溃。

nn

nn

//编辑:

我知道Debug.Log(Test[4].ToString()); //Exception!!是错误的并且会调用异常(!!!)。它被通缉。通过try {}块来实现,但请记住脚本是第三方制作的。我没有掌握这一点,但至少我不知道我们的应用程序正在处理错误(并在richTextBox中显示它们),而不是抛出它们(=应用程序崩溃)。

TLDR:我想阻止加载到我的程序集中的第三方程序集使我的程序崩溃

2 个答案:

答案 0 :(得分:2)

如果我了解它,您只需要捕获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
}

有关可能导致第二个阻止的所有可能异常,请参阅MSDN。您可能只想在try块中包装所有代码(从加载程序集开始),因为这些代码也会失败。

您还应该调查AppDomains,它们是像这样做隔离的“正确”方式。他们加入CLR以提供比您自己可能管理的更多保护。

答案 1 :(得分:0)

int[] Test = { 0, 3 };

此行将Test数组大小设置为2,因此您可以从中获取的唯一项目是:

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

这就是Debug.Log(Test[4].ToString());抛出异常的原因。

要抓住它,您必须在调用try方法时使用catch / Test阻止:

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