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.
Solved! Go to Solution.
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.
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