objDoc.Close() crashes SE

Valued Contributor
Valued Contributor

Like, probably, many of you I've written a small code to export drawings from SE to .dwg, dxf and pdf.

 

Prior to the export a small form will be shown allowing the user to select the desired file types.

When the user click the Run command the following thread is started:

 

 

Private Sub ThreadTask()
        Dim soloFilename As String = ""
        For Each itm As ListViewItem In LVFiles.Items
            TsProgress.Value = itm.Index
            If itm.Checked Then
                soloFilename = Path.GetFileNameWithoutExtension(itm.Text)
                objDoc = objApplication.Documents.Open(Filename:=DefaultLocation & "\" & itm.Text) 'open file
                objDoc = objApplication.ActiveDocument
                If ChPDF.Checked = True Then
                    objDoc.SaveAs(ExportToLocation & "\Export\PDF\" & soloFilename & ".pdf")
                    objApplication.DoIdle()
                End If
                If ChDWG.Checked = True Then
                    objDoc.SaveAs(ExportToLocation & "\Export\DWG\" & soloFilename & ".dwg")
                    objApplication.DoIdle()
                End If
                If ChDXF.Checked = True Then
                    objDoc.SaveAs(ExportToLocation & "\Export\DXF\" & soloFilename & ".dxf")
                    objApplication.DoIdle()
                End If
            End If
            'IT CRASHES HERE!
            objDoc.Close()
            objApplication.DoIdle() 'this didn't solve it
            Marshal.ReleaseComObject(objDoc) 'neither did this
        Next
        lbStatus2.Text = "Finished"
        btnCancel.Enabled = False
        btnRun.Enabled = True
        Me.Focus()
    End Sub

 

I figured SE would still be busy saving or whatever so I added the "objApplication.DoIdle()" after the save and close commands to no avail.

Maarten Elings | Mechanical Engineer
3 REPLIES

Re: objDoc.Close() crashes SE

Solution Partner Phenom Solution Partner Phenom
Solution Partner Phenom

You're running into a classic .NET COM Interop \ Garbage Collection (GC) issue. See my OpenSave sample on GitHub. Specifically, see my openSaveBackgroundWorker_DoWork on line 184. It leverages the IsolatedTask class from the SolidEdge.Community NuGet Package that I provide. This class does all of the hard work of creating a separate AppDomain to execute your COM Interop code in. After execution, the AppDomain is torn down and all Runtime Callable Wrappers (RCW) are immediately freed.

 

I'll be the first to admit that it sucks having to deal with this but it's out of our control. In my experience, this solution is the best solution. If you'll take the time to learn from the OpenSave sample, your issues will go away. I promise.

Jason Newell
Applications Architect
www.jasonnewell.net

Re: objDoc.Close() crashes SE

Valued Contributor
Valued Contributor

Thank you for your explanation.

I Took the time to examine, understand and rewrite your example to an isolatedtask of my own to batch-save pdf's.

To (possibly) aid others who endeavour the same quest.

This is my wewritten code to save a batch of drawings to PDF:

 

 

Imports SolidEdgeCommunity
Imports SolidEdgeCommunity.Extensions ' https://github.com/SolidEdgeCommunity/SolidEdge.Community/wiki/Using-Extension-Methods
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.IO
Imports System.Runtime.InteropServices

Public Class ExportDwg
    Inherits IsolatedTaskProxy

    Public Sub DoOpenSave(ByVal filePath As String, ByVal destination As String)
        InvokeSTAThread(Of String, String)(AddressOf DoOpenSaveInternal, filePath, destination)
    End Sub

    Private Sub DoOpenSaveInternal(ByVal filePath As String, ByVal destination As String)
        ' Register with OLE to handle concurrency issues on the current thread.
        SolidEdgeCommunity.OleMessageFilter.Register()
        Try
            Dim application_Export As SolidEdgeFramework.Application = SolidEdgeCommunity.SolidEdgeUtils.Connect(True)
            Dim documents As SolidEdgeFramework.Documents = Nothing
            Dim document_Export As SolidEdgeFramework.SolidEdgeDocument = Nothing

            ' Disable (most) prompts.
            application_Export.DisplayAlerts = False

            ' Get a reference to the documents collection.
            documents = application_Export.Documents

            ' Determine filename without extension
            Dim soloFilename As String = Path.GetFileNameWithoutExtension(filePath)

            ' Open the file.
            document_Export = documents.Open(Of SolidEdgeFramework.SolidEdgeDocument)(filePath)
            document_Export = application_Export.ActiveDocument
            document_Export.SaveAs(destination & "\Export\PDF\" & soloFilename & ".pdf")
            ' Give SE a break to complete the save task
            application_Export.DoIdle()

            ' Close document.
            document_Export.Close()
            application_Export.DoIdle()
        Catch ex As Exception
            MsgBox(ex.Message)

        Finally
            SolidEdgeCommunity.OleMessageFilter.Unregister()
        End Try
    End Sub

    Private Sub DisableAddins(ByVal application As SolidEdgeFramework.Application)
        Dim addins As SolidEdgeFramework.AddIns = Nothing
        Dim addin As SolidEdgeFramework.AddIn = Nothing

        addins = application.AddIns

        For i As Integer = 1 To addins.Count
            addin = addins.Item(i)
            addin.Connect = False
        Next i
    End Sub

 

 

Maarten Elings | Mechanical Engineer

Re: objDoc.Close() crashes SE

Solution Partner Phenom Solution Partner Phenom
Solution Partner Phenom

Thanks for the feedback. I've been wondering how things were going for you. I'm always glad to hear that my open source work is of use.

Jason Newell
Applications Architect
www.jasonnewell.net