• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012
    Accepted Solution

    Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    332 Views, 29 Replies
    01-29-2013 05:36 AM

    I am trying to run acad code from a WCF service in process.  I get most everything work just fine but for some reason I get this cryptic error when I try to loop through a selection set of AcadEntity objects.  The weird part is that if I place the same loop in a simple IExtensionApplication command it works fine.

     

    Does anyone have any suggestions how to make this work?  I assume something to do with wcf service behavior/acad threading model but not sure what.

     

    Here is the full source code, note that I am not using Editor.WriteMessage because that's one of the things I cannot get working from WCF so I am relying on NLog to generate the output on the bottom of this message. If you have an idea how to make Editor.WriteMessage work from WCF I'd appreciate your help as well.

     

    Thanks in advance,

    Steve 

     

    Imports System.ServiceModel

    Imports System.ServiceModel.Description

    Imports Autodesk.AutoCAD.Runtime

    Imports Autodesk.AutoCAD.Interop

    Imports Autodesk.AutoCAD.Interop.Common

    Imports Autodesk.AutoCAD.ApplicationServices

    Imports MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application

    Imports NLog

     

    #Region "WCF SERVICE"

    <ServiceContract()>

    Public Interface ISelectItems

        <OperationContract()>

        Sub SelectItems()

    End Interface

     

    <ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single, ConcurrencyMode:=ConcurrencyMode.Single)>

    Public Class wcfSelectItems

        Implements ISelectItems

        Private log As Logger = LogManager.GetCurrentClassLogger

        Public Sub SelectItems() Implements ISelectItems.SelectItems

            log.Info("This will crash")

            DoSelection()

        End Sub

        Public activeDoc As Document = MgdAcApplication.DocumentManager.MdiActiveDocument

        Public Sub DoSelection()

            Try

                Using acDocLck As DocumentLock = activeDoc.LockDocument()

                    Dim td As AcadDocument = DocumentExtension.GetAcadDocument(activeDoc)

                    Dim ssetObj As AcadSelectionSet = td.SelectionSets.Add("SSALL0")   ' creates named selection set

                    ssetObj.Select(AcSelect.acSelectionSetAll)

                    log.Trace("We have a selection of size = {0}", ssetObj.Count)

                    Try

                        For Each ent As AcadEntity In ssetObj

                            log.Trace("{0}", ent.ObjectName)

                        Next

                    Catch

                        log.Error("This is the crash: '{0}'", Err.Description)

                    End Try

                End Using

            Catch

                log.Error(Err.Description)

            End Try

        End Sub

     

    End Class

    #End Region

     

     

    Public Class clsSelectedItems

        Implements IExtensionApplication

        Private log As Logger = LogManager.GetCurrentClassLogger

     

    #Region "ACAD COMMAND"

        <CommandMethod("DoSelection")> _

        Public Sub DoSelection_Method()

            log.Info("This is OK")

            DoSelection()

        End Sub

    #End Region

     

        Public m_DefaultService As String = "ISelectItems"

        Public m_DefaultIP As String = "127.0.0.1"

        Public m_DefaultPort As String = "7200"

        Public m_DefaultProtocol As String = "http"

        Private m_serviceHost As ServiceHost = Nothing

     

        Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize

            hostService(m_DefaultIP, m_DefaultPort)

        End Sub

     

        Public Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate

            If Not m_serviceHost Is Nothing Then

                m_serviceHost.Close()

            End If

        End Sub

        Public activeDoc As Document = MgdAcApplication.DocumentManager.MdiActiveDocument

     

        'Do selection routine, exact same as above.  This one works:

        Public Sub DoSelection()

            Try

                Using acDocLck As DocumentLock = activeDoc.LockDocument()

                    Dim td As AcadDocument = DocumentExtension.GetAcadDocument(activeDoc)

                    Dim ssetObj As AcadSelectionSet = td.SelectionSets.Add("SSALL1")   ' creates named selection set

                    ssetObj.Select(AcSelect.acSelectionSetAll)

                    log.Trace("We have a selection of size = {0}", ssetObj.Count)

                    Try

                        For Each ent As AcadEntity In ssetObj

                            log.Trace("{0}", ent.ObjectName)

                        Next

                    Catch

                        log.Error("This is the crash: '{0}'", Err.Description)

                    End Try

                End Using

            Catch

                log.Error(Err.Description)

            End Try

        End Sub

     

        ' Set up a WCF service endpoint and start service

        Public Sub hostService(ByVal _hostIP As String, ByVal _port As String)

            Dim wcfEndpoint As String = String.Format("{0}://{1}:{2}/{3}", m_DefaultProtocol, _hostIP, _port, m_DefaultService)

            Try

                Dim baseAddress As Uri = New Uri(wcfEndpoint)

                m_serviceHost = New ServiceHost(GetType(wcfSelectItems), baseAddress)

                Dim binding = CreateNewHttpBinding(GetType(wcfSelectItems).FullName)

                m_serviceHost.AddServiceEndpoint(GetType(ISelectItems), binding, "IAcadInProc")

                Dim smb As New ServiceMetadataBehavior()

                smb.HttpGetEnabled = True

                m_serviceHost.Description.Behaviors.Add(smb)

            Catch ex As Exception

                log.Error("EX 2. {0}", ex.ToString)

            End Try

            m_serviceHost.Open()

            log.Info("Listening on {0}", wcfEndpoint)

        End Sub

     

        'We avoid using config files for now:

        Private Shared Function CreateNewHttpBinding(ByVal name As String) As WSHttpBinding

            Dim result As New WSHttpBinding

            result.Name = name

            result.OpenTimeout = New TimeSpan(0, 1, 0)

            result.ReceiveTimeout = New TimeSpan(0, 10, 0)

            result.SendTimeout = New TimeSpan(0, 1, 0)

            result.BypassProxyOnLocal = False

            result.TransactionFlow = False

            result.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard

            result.MaxBufferPoolSize = 2147483647

            result.MaxReceivedMessageSize = 2147483647

            result.MessageEncoding = WSMessageEncoding.Text

            result.TextEncoding = System.Text.Encoding.UTF8

            result.UseDefaultWebProxy = True

            result.AllowCookies = False

            result.ReaderQuotas.MaxStringContentLength = 2147483647

            result.ReaderQuotas.MaxDepth = 12

            result.ReaderQuotas.MaxArrayLength = 16384

            result.ReaderQuotas.MaxBytesPerRead = 4096

            result.ReaderQuotas.MaxNameTableCharCount = 16384

            result.ReliableSession.Ordered = False

            result.ReliableSession.InactivityTimeout = New TimeSpan(0, 10, 0)

            result.ReliableSession.Enabled = False

            result.Security.Mode = SecurityMode.None

            result.Security.Transport.ClientCredentialType = HttpClientCredentialType.None

            result.Security.Message.ClientCredentialType = MessageCredentialType.None

            Return (result)

        End Function

    End Class

     

     

    OUTPUT:

     

    Info    clsSelectedItems     Listening on http://127.0.0.1:7200/ISelectItems
    Info    wcfSelectItems       This will crash
    Trace    wcfSelectItems     We have a selection of size = 200
    Error    wcfSelectItems       This is the crash: 'Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))'
    Info    clsSelectedItems       This is OK
    Trace    clsSelectedItems       We have a selection of size = 200
    Trace    clsSelectedItems       AcDbText
    Trace    clsSelectedItems       AcDbViewport
    Trace    clsSelectedItems       AcDbViewport
    % <--------------ETC. CUT------------->%

     

    Please use plain text.
    Valued Contributor
    Posts: 78
    Registered: ‎12-04-2009

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 08:10 AM in reply to: sszabo

    How do you get the first example that does not work to run?  It looks like you might be trying to use a mix of ObjectARX .NET and COM and run out of process.

     

    If you are not netloading the assembly in-process then the ObjectARX .NET will not work.

     

    Change the first example to only use COM, or do as you did in the second and get your service running through the initialize method to allow you to use the .NET API.

    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 08:33 AM in reply to: tonofsteel

    If you copy and paste the code into a new VB Class Project and add the following references it should work as advertised, that's how I got the output. 

     

    AcCoreMgd

    AcDBMgd

    AcMgd

    Autodesk.AutoCAD.Interop

    Autodesk.AutoCAD.Interop.Common

    NLog

    System.Runtime.Serialization

    System.ServiceModel

     

    When you say "it doesn't work" please let me know where are you getting stuck?

     

    After compiled this DLL should be netloaded and it should host the WCF service automatically on http://127.0.0.1:7200/ISelectItems endpoint as the logs indicate.

     

    That's my problem, as a newbie I am not very good with the .NET API and there are things I simply couldn't make work with it.  For instance AcadSelectionSet.  If you have some code example showing what you mean I'd appreciate your effort. 

     

    My idea of a quick and dirty solution to this problem for now is to just create ACAD commands for what doesn't work directly and send these commands in the service requests instead of trying to make ACAD play nice with WCF because I can still call ActiveDocument.SendCommand() from WCF.

     

    Please use plain text.
    Valued Contributor
    Posts: 78
    Registered: ‎12-04-2009

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 08:37 AM in reply to: tonofsteel

    How do you load and get this part of the code to run on its own:

     

    Imports System.ServiceModel
    
    Imports System.ServiceModel.Description
    
    Imports Autodesk.AutoCAD.Runtime
    
    Imports Autodesk.AutoCAD.Interop
    
    Imports Autodesk.AutoCAD.Interop.Common
    
    Imports Autodesk.AutoCAD.ApplicationServices
    
    Imports MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application
    
    Imports NLog
    
     
    
    #Region "WCF SERVICE"
    
    <ServiceContract()>
    
    Public Interface ISelectItems
    
        <OperationContract()>
    
        Sub SelectItems()
    
    End Interface
    
     
    
    <ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single, ConcurrencyMode:=ConcurrencyMode.Single)>
    
    Public Class wcfSelectItems
    
        Implements ISelectItems
    
        Private log As Logger = LogManager.GetCurrentClassLogger
    
        Public Sub SelectItems() Implements ISelectItems.SelectItems
    
            log.Info("This will crash")
    
            DoSelection()
    
        End Sub
    
        Public activeDoc As Document = MgdAcApplication.DocumentManager.MdiActiveDocument
    
        Public Sub DoSelection()
    
            Try
    
                Using acDocLck As DocumentLock = activeDoc.LockDocument()
    
                    Dim td As AcadDocument = DocumentExtension.GetAcadDocument(activeDoc)
    
                    Dim ssetObj As AcadSelectionSet = td.SelectionSets.Add("SSALL0")   ' creates named selection set
    
                    ssetObj.Select(AcSelect.acSelectionSetAll)
    
                    log.Trace("We have a selection of size = {0}", ssetObj.Count)
    
                    Try
    
                        For Each ent As AcadEntity In ssetObj
    
                            log.Trace("{0}", ent.ObjectName)
    
                        Next
    
                    Catch
    
                        log.Error("This is the crash: '{0}'", Err.Description)
    
                    End Try
    
                End Using
    
            Catch
    
                log.Error(Err.Description)
    
            End Try
    
        End Sub
    
     
    
    End Class
    
    #End Region

     

    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 08:53 AM in reply to: tonofsteel

    This is just the WCF interface. You have to host it in the clsSelectedItems class by calling the hostService() Sub  and if you do that from Initialize() that will happen automatically when you netload the DLL.  Again, I put all these classes in 1 file intentionally so that people can simply copy/paste into a new class project and should be ready to go.   If that doesn't work for you please tell me what's the error you are getting.

     

    Just a followup on my previous idea: sending the command from the WCF class still gives me this error which is unbelievable because it's executing directly in my IExtensionApplication class and if I invoke the VERY SAME function from the acad command directly it works fine.  This is the strangest thing I've ever seen.

    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 09:21 AM in reply to: sszabo

    Here is what I am talking about:

     

    If you add the following helper function to wcfSelectItems, you should be able to invoke any ACAD command from WCF remotely:

     

        Private ReadOnly Property Acad() As AcadApplication

            Get

                Return DirectCast(Application.AcadApplication, AcadApplication)

            End Get

        End Property

     

        Public Sub SendCommand(ByVal cmd As String)

            Using acDocLck As DocumentLock = activeDoc.LockDocument()

                Try

                    Dim cmdStr As String = "(command " + Chr(34) + cmd + Chr(34) + " " + ")" + vbCr

                    Acad.ActiveDocument.SendCommand(cmdStr)

                Catch

                    log.Error("EX 5. {0}", Err.Description)

                End Try

            End Using

        End Sub

     

    And this works with any standard commands such as "RIBBONCLOSE" or "NETLOAD" etc.  However when I call it for the DoSelection command above it gives me the SAME EXACT E_UNEXPECTED error on the SAME EXACT LINE!  Any ideas?!

     

    ps.  To Invoke this from the wcf interface you'll have to also add the following to ISelectItems:

     

        <OperationContract()>

        Sub AcadCmdSelectItems()

     

    and the following to wcfSelectItems:

     

        Public Sub AcadCmdSelectItems() Implements ISelectItems.AcadCmdSelectItems

            SendCommand("DoSelection")

        End Sub

     

    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 10:06 AM in reply to: tonofsteel

    It just occured to me that this post doesn't contain some basic info on how to test a WCF server out of the box.  After compiling the code above you netload the DLL and then ACAD should be hosting and listening for WCF clients.  To actually invoke DOSELECTION from WCF you can use WCF Test Client that comes with .NET:

     

    http://msdn.microsoft.com/en-us/library/bb552364.aspx

     

    Please use plain text.
    Valued Contributor
    Posts: 78
    Registered: ‎12-04-2009

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 10:42 AM in reply to: sszabo

    I have not been able to get this code running to reproduce your error.

     

    When I navigate to the page I get the service info.

     

    The logger does not log.

     

    When I try to use WcfTestClient.exe I get exception Object Reference not set to an instance of an object for any URL that I enter.

    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 11:57 AM in reply to: tonofsteel

    Ok, I see. I appreciate your effort, if you still have some patience try these tips:

     

    A.The logger does not log.

     

    This is important because this is how you know that your service is hosted correctly in ACAD and what's the exact endpoint it's listening on.  Try the following steps:

     

    1) Install the latest NLog from here: http://nlog-project.org/download

    2) Add a New Item to your VB Class Project and select NLog Configuration File.  This will create an NLog.config file with default target going to "${basedir}/log.txt" where ${basedir} is your ACAD directory (For me that's C:\Program Files\Autodesk\AutoCAD 2013).  Copy this config file in your autocad directory. (Alternatively you can specify to Copy Always to your project output directory and set that to ACAD path).  You also have to copy C:\Program Files (x86)\NLog\.NET Framework 4.0\NLog.dll in your ACAD directory (provided you are using NLog 4.0 in your project)

     

    Optionally you can also view your logs in real time as opposed to opening log.text all the time:

    http://log2console.codeplex.com/

     

    B) When I try to use WcfTestClient.exe I get exception Object Reference not set to an instance of an object for any URL that I enter.

     

    You can open log.txt in your ACAD directory and copy the exact URL from the first line:

     

    2013-01-29 13:50:36.7247|INFO|clsWcfTestPrj.clsSelectedItems|Listening on http://127.0.0.1:7200/ISelectItems

     

    In WCF test client click File -> Add Service and paste in the blue URL above.  When connected you should be able to see the SelectItems request and you should be able to push the Invoke button.  In the logs you will see the error code.  Then you can go to ACAD command line and type in DOSELECTION and see all the selection objects listed provided you had a drawing open with objects in it.

     

    Hope this will work, let me know if you need any more help.

     

     

    Please use plain text.
    Valued Contributor
    Posts: 78
    Registered: ‎12-04-2009

    Re: Catastrophic failure HRESULT: 0x8000FFFF (E_UNEXPECTED)

    01-29-2013 12:00 PM in reply to: sszabo

    WcfTestClient.exe will not work on my setup.  It always crashes and never loads up the service.  I got WCFStorm and got the logger going (config file needed to be in autoCAD directory for it to start writing files).

     

    I now have the same error you were getting and it is getting logged. 

    Please use plain text.