代码之家  ›  专栏  ›  技术社区  ›  Wolfwyrd

从通过反射调用的COM方法检索原始错误号

  •  0
  • Wolfwyrd  · 技术社区  · 18 年前

    f_oType = Type.GetTypeFromProgID(MyProgId);
    f_oInstance = Activator.CreateInstance(f_oType);
    

    f_oType.InvokeMember("Process", BindingFlags.InvokeMethod, null, f_oInstance, new object[] { param1, param2, param3, param4 });
    

    我捕获任何引发的TargetNotificationException进行日志记录,并可以从TargetNotificationException.InnerException字段获取详细的错误描述。但是,我知道COM组件使用Error.Raise生成错误号,我需要在调用.Net应用程序时以某种方式获取该错误号。

    问题似乎源于TargetInvocationException不包含错误号,如果它是一个正常的COMException,那么我会预料到这一点,因此:

    如何从.Net代码中的COM对象获取错误号?

    或

    当COM组件发生故障时,我是否可以以导致COMException(包含错误号)而不是TargetInvocationException的方式进行相同的调用?

    还请注意,目标平台是.Net 2.0,我确实可以访问VB6源代码,但将修改从VB6引发的错误消息以包含错误代码作为文本的一部分视为有点黑客行为。

    3 回复  |  直到 6 年前
        1
  •  2
  •   Ichiro Furusato    18 年前

    我更仔细地查看了您的代码,通过反射处理TargetInvocationException并处理内部异常,即COMException。。。下面的代码示例(我也运行并测试了它):

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                var f_oType = Type.GetTypeFromProgID("Project1.Class1");
                var f_oInstance = Activator.CreateInstance(f_oType);
                f_oType.InvokeMember("Test3", BindingFlags.InvokeMethod, null, f_oInstance, new object[] {});
            }
            catch(TargetInvocationException ex)
            {
                //no need to subtract -2147221504 if non custom error etc
                int errorNumber = ((COMException)ex.InnerException).ErrorCode - (-2147221504);
                MessageBox.Show(errorNumber.ToString() + ": " + ex.InnerException.Message);
            }
            catch(Exception ex)
            { MessageBox.Show(ex.Message); }
        }
    
        2
  •  2
  •   Ichiro Furusato    18 年前

    您将处理COMException并使用该异常对象的ErrorCode属性。通常在visual basic DLL中,如果抛出自定义错误,则会使用以下命令引发错误:

    如果是这种情况,则需要从异常错误代码中减去vbobjecterror(-2147221504)以获得实际错误号。如果不是,请使用ErrorCode值。

    示例VB dll代码:(来自Project1.Class1)

    MsgBox "this is a test 3"
    Err.Raise vbObjectError + 88, "Project1.Class1.Test3()", "Forced error test"
    

    示例C#消耗处理代码:

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                var p = new Class1();
                p.Test3();
            }
            catch (COMException ex)
            {
                int errorNumber = (ex.ErrorCode - (-2147221504));
                MessageBox.Show(errorNumber.ToString() + ": " + ex.Message);
            }
            catch(Exception ex)
            { MessageBox.Show(ex.Message); }
        }
    

    我刚刚完成的这个测试中的错误代码按预期返回88。

        3
  •  2
  •   Robert Paulson    18 年前

    catch(TargetInvocationException ex)
    {
        if( ex.InnerException != null && ex.InnerException is COMException )
        {
            COMException ce = (COMException)ex.InnerException;
            // do something with ce - e.g. logging the error
        }
        // else InnerException not set, or it's not a COMException
    }