문제

.NET 메소드에서 호출 해야하는 VB6 COM 구성 요소가 있습니다. 반사를 사용하여 COM 객체의 인스턴스를 만들고 다음과 같은 방식으로 활성화합니다.

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

내가 인스턴스화 해야하는 유형의 프로그램이 다를 수 있으므로 com dll에 대한 라이브러리를 만들기 위해 tlbimp를 사용하는 대신 gettypefromprogid를 사용해야합니다. 그런 다음 type.invokemember를 사용하여 코드에서 COM 메소드를 호출합니다.

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

로깅을 위해 TargetInvocationException을 올렸으며 TargetInVocationException.inNerexception 필드에서 자세한 오류 설명을 얻을 수 있습니다. 그러나 COM 구성 요소가 Error.Raise를 사용하여 오류 번호를 생성하고 Calling .NET 응용 프로그램 에서이 문제를 해결해야한다는 것을 알고 있습니다.

문제는 TargetInvocationException에서 오류 번호를 포함하지 않는 것으로 보입니다.

.NET 코드의 COM 개체에서 오류 번호를 얻으려면 어떻게해야합니까?

또는

COM 구성 요소가 실패 할 때 TargetInvocationException이 아닌 ComeXception (오류 번호 포함)을 유발하는 방식으로 동일한 호출을 할 수 있습니까?

또한 대상 플랫폼은 .NET 2.0이며 vb6 소스 코드에 액세스 할 수 있지만 텍스트의 일부로 오류 코드를 약간 해킹하기 위해 vb6에서 제기 된 오류 메시지 변경을 고려합니다.

도움이 되었습니까?

해결책

나는 당신의 코드를 조금 더 가깝게 보았고 반사를 통해 targetInvocationException을 처리하고 아래의 코드 예제 인 내부 예외와 함께 작업합니다 (아래에도 실행 및 테스트).

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

다른 팁

ComeXception을 처리하고 해당 예외 객체의 ErrorCode 속성을 사용합니다. 일반적으로 Visual Basic DLL에서 사용자 지정 오류를 던지는 경우 err.raise vbobjecterror + 88, "project1.class1.test3 ()", "강제 오류 테스트"로 오류가 발생합니다.

이 경우 예외 ErrorCode에서 vbobjecterror (-2147221504)를 빼서 실제 오류 번호를 얻습니다. 오류 코드 값 만 사용하지 않는 경우

예제 vb dll 코드 : (project1.class1에서)

공개 하위 테스트 3 ()

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

이 테스트에서 ErrorCode는 예상대로 88을 반환했습니다.

@Sharvell의 캐치 코드에 대한 업데이트를 제공하고 싶어요. innerexception이 comexception이라고 확실하지 않으면 먼저 안전하게 테스트하는 것이 좋습니다. 그렇지 않으면 예외 핸들러에서 예외가 있습니다. 멍청이!

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
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top