Link to home
Start Free TrialLog in
Avatar of chlade
chlade

asked on

Problem passing exception from AppDomain

I have an application that calls a routine within an AppDomain.  The AppDomain will raise an event outside the AppDomain called StatusUpdate.  It will possibly pass back a SystemException object.

In general, this works fine.  However, if I call the AppDomain routine from a form (versus a console app or a windows service), then the exception will not properly pass back all pieces of a Soap Exception.

Specifically, I want the Detail attribute of the Soap Exception.  I can see that it has a value in the AppDomain but when this value is passed back via the event call, the detail gets lost.

I attached the code for a small app that demonstrates the problem.  Here is the output of the application:

Inside AppDomain
   Message: test
   Detail:  <A>1</A>
Outside AppDomain
   Message: test
   Detail:  Nothing


I am not all that well-versed in AppDomains and would appreciate any ideas that might help me get to the bottom of the problem.

Thanks,
Chris
Imports System.Web.Services.Protocols

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim exeAssembly As String = System.Reflection.Assembly.GetExecutingAssembly().FullName

        Dim ads As New AppDomainSetup()
        ads.ApplicationBase = System.Environment.CurrentDirectory
        ads.DisallowBindingRedirects = False
        ads.DisallowCodeDownload = True
        ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile

        Dim ad2 As AppDomain = AppDomain.CreateDomain("TestMapAppDomain", Nothing, ads)

        Dim mbrt As MarshalByRefType = CType(ad2.CreateInstanceAndUnwrap(exeAssembly, GetType(MarshalByRefType).FullName), MarshalByRefType)

        AddHandler mbrt.StatusUpdate, AddressOf ProcessQueueRecord_StatusUpdate

        mbrt.RunTest()

        End

    End Sub

    Private Sub ProcessQueueRecord_StatusUpdate(ByVal ex As Exception)

        Console.WriteLine("Outside AppDomain")
        Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
        Console.WriteLine("   Message: " & soapex.Message)
        If soapex.Detail IsNot Nothing Then
            Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
        Else
            Console.WriteLine("   Detail:  Nothing")
        End If

        Console.WriteLine(ex.Message)

    End Sub


    Public Class MarshalByRefType
        Inherits MarshalByRefObject

        Public Event StatusUpdate(ByVal ex As Exception)

        Sub RunTest()

            Try
                Dim xmldoc As New Xml.XmlDocument
                xmldoc.LoadXml("<A>1</A>")
                Throw New System.Web.Services.Protocols.SoapException("test", New System.Xml.XmlQualifiedName(), "", xmldoc.FirstChild)
            Catch ex As Exception
                Console.WriteLine("Inside AppDomain")
                Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
                Console.WriteLine("   Message: " & soapex.Message)
                If soapex.Detail IsNot Nothing Then
                    Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
                Else
                    Console.WriteLine("   Detail:  Nothing")
                End If
                RaiseEvent StatusUpdate(ex)
            End Try

        End Sub

    End Class

End Class

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Dabas
Dabas
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of chlade
chlade

ASKER

Thanks.  Yeah, unfortunately that won't really help me.  In my actual application, the AppDomain actually calls a user-defined "plug in" dll.  It won't only be Soap exceptions.  I just want to make sure that all exceptions of all types are passed back in their entirety so that the main application can report them accurately.

What is interesting is that if you put the logic in the Form Load and skip the AppDomain altogether, it works fine.  As a test I put this code in the Form Load event and it works fine.
Try
            Try
                Try
                    Dim xmldoc As New Xml.XmlDocument
                    xmldoc.LoadXml("<A>1</A>")
                    Throw New System.Web.Services.Protocols.SoapException("test", New System.Xml.XmlQualifiedName(), "", xmldoc.FirstChild)
                Catch ex As Exception
                    Throw New Exception(ex.Message, ex)
                End Try
            Catch ex As Exception
                Throw New Exception(ex.Message, ex)
            End Try
        Catch ex As Exception
            Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
            Console.WriteLine("   Message: " & soapex.Message)
            If soapex.Detail IsNot Nothing Then
                Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
            Else
                Console.WriteLine("   Detail:  Nothing")
            End If
        End Try

Open in new window

That does not come as a surprise.
This code is not crossing between domains.
That is where things are getting lost