Add in PDM API causes SW & Explorer Crash

As I stated I am working on an add in that causes whatever it is interacting with to crash when ran, the code checks for the correct state: will create a pdf, and move it and another file to a drawing folder. This works, but after it completes, whatever is used to change state crashes, it seems to work perfectly once, but not again. Windows file explorer crashes in any state change, and solidworks crashes after the full code runs. The code has changed a lot as I try and fix the issue, so I will include the first code I got working.
It is based off of the solidworks reference code that runs at state change, and I can include the dll file if for some reason someone wants to troubleshoot that instead of just looking over code.

 

I assume I am releasing something I am not supposed to, or the opposite, but I cannot figure it out, any tips are appreciated.

 

Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text


Public Class DrawingCheckInHandler
   Implements IEdmAddIn5

   ' --- CONFIGURATION CONSTANTS ---
   Private Const DRAWINGS_BASE_PATH As String = "C:\Users\default\Desktop\Drawings"
   Private Const ARCHIVE_BASE_PATH As String = "C:\Users\default\Desktop\Archive"
   Private Const REVISION_PROPERTY_NAME As String = "*Revision"
   ' --- END CONFIGURATION CONSTANTS ---

   Private Const LOG_FILE_NAME As String = "PdmDrawingCheckInHandlerLog.txt"

   ' --- TEMPORARY: For testing with a hardcoded path ---
   Private Const USE_HARDCODED_SLDDRW_PATH As Boolean = False ' SET TO True TO USE, False TO TRY PDM GetLocalPath
   Private Const HARDCODED_SLDDRW_PATH As String = "C:\Users\default\Sandbox\New Folder\999-9999.SLDDRW"
   ' --- END TEMPORARY ---

   Private Shared conversionInProgress As Boolean = False

#Region "IEdmAddIn5 Implementation"

   Public Sub GetAddInInfo(ByRef poInfo As EdmAddInInfo,
                           ByVal poVault As IEdmVault5,
                           ByVal poCmdMgr As IEdmCmdMgr5) Implements IEdmAddIn5.GetAddInInfo
       Try
           poInfo.mbsAddInName = "Drawing PDF Processor"
           poInfo.mbsCompany = "Your Company Name"
           poInfo.mbsDescription = "Archives old PDF and creates new PDF during drawing check-in."
           poInfo.mlAddInVersion = 1
           poInfo.mlRequiredVersionMajor = 25 ' Corresponds to PDM 2017 (for IEdmFile17 features)
           poInfo.mlRequiredVersionMinor = 1

           poCmdMgr.AddHook(EdmCmdType.EdmCmd_PostState)
           poCmdMgr.AddHook(EdmCmdType.EdmCmd_PostUnlock)
           LogMessage("Add-in loaded. Hook registered for EdmCmd_PostUnlock.")

           If USE_HARDCODED_SLDDRW_PATH Then
               LogMessage("WARNING: USE_HARDCODED_SLDDRW_PATH is TRUE. Add-in will only process: " & HARDCODED_SLDDRW_PATH)
           End If
       Catch ex As Runtime.InteropServices.COMException
           'MessageBox.Show("HRESULT = 0x" + ex.ErrorCode.ToString("X") + vbCrLf + ex.Message)
       Catch ex As Exception
           LogMessage(\$"Error in GetAddInInfo: {ex.ToString()}")
           'MessageBox.Show(\$"Error initializing add-in: {ex.Message}", "Add-in Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
       End Try
   End Sub

   Public Sub OnCmd(ByRef poCmd As EdmCmd, ByRef ppoData As EdmCmdData()) Implements IEdmAddIn5.OnCmd
       LogMessage("OnCmd method ENTERED.")
       Dim vault As IEdmVault5 = Nothing
       Try
           If poCmd.mpoVault Is Nothing Then
               LogMessage("OnCmd: poCmd.mpoVault is Nothing. Exiting.")
               Return
           End If
           vault = TryCast(poCmd.mpoVault, IEdmVault5)
           If vault Is Nothing Then
               LogMessage("Vault is null after TryCast. Exiting.")
               Return
           End If

           LogMessage(\$"Connected to PDM Vault: {vault.Name}. OnCmd: {poCmd.meCmdType.ToString()}.")
           If ppoData Is Nothing OrElse ppoData.Length = 0 Then
               LogMessage("ppoData is empty. Exiting.")
               Return
           End If
           LogMessage(\$"ppoData contains {ppoData.Length} item(s).")

           Select Case poCmd.meCmdType
               Case EdmCmdType.EdmCmd_PostState
                   LogMessage("OnCmd: EdmCmd_PostState MET.")
                   Dim affectedFileNames As String = ""
                   For Each affectedFile As EdmCmdData In ppoData
                       Dim newStateName As String = affectedFile.mbsStrData2
                       LogMessage(\$"File '{affectedFile.mbsStrData1}' new state: '{newStateName}'")
                       If newStateName IsNot Nothing AndAlso newStateName.Trim().ToUpper() = "REV IN PROCESS" Then
                           affectedFileNames += affectedFile.mbsStrData1 + vbCrLf

                           ' Your PDF processing logic
                           Dim fileId As Integer = affectedFile.mlObjectID1
                           Dim parentFolderIdFromCmdData As Integer = affectedFile.mlObjectID3
                           If fileId > 0 Then
                               Dim fileAsObject As Object = Nothing
                               Try
                                   fileAsObject = vault.GetObject(EdmObjectType.EdmObject_File, fileId)
                                   Dim baseFileNameForLog As String = affectedFile.mbsStrData1
                                   ProcessDrawingFile(fileAsObject, parentFolderIdFromCmdData, vault, baseFileNameForLog)
                               Catch fileEx As Exception
                                   LogMessage(\$"Error processing file ID {fileId}: {fileEx.ToString()}")
                                   'MessageBox.Show(\$"Error for file ID {fileId}: {fileEx.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                               Finally
                                   If fileAsObject IsNot Nothing Then
                                       Marshal.ReleaseComObject(fileAsObject)
                                       fileAsObject = Nothing
                                   End If
                               End Try
                           Else
                               LogMessage(\$"Invalid FileID {fileId}. Skipping.")
                           End If
                       End If

                       ' Show if this is a top node in the transition
                       Try
                           Dim cmdNode As IEdmCmdNode = TryCast(affectedFile.mpoExtra, IEdmCmdNode)
                           If cmdNode IsNot Nothing Then
                               Dim topNode As Boolean = cmdNode.GetProperty(EdmCmdNodeProp.EdmCmdNode_IsTopNode)
                               LogMessage(\$"File '{affectedFile.mbsStrData1}' is top node? {topNode}")
                           End If
                       Catch ex As Exception
                           LogMessage("Error checking top node: " & ex.Message)
                       End Try
                   Next

                   If affectedFileNames.Length > 0 Then
                       poCmd.mpoVault.MsgBox(poCmd.mlParentWnd, affectedFileNames + " has been released.")
                   End If

               Case Else
                   poCmd.mpoVault.MsgBox(poCmd.mlParentWnd, "An unknown command type was issued.")
           End Select

       Catch ex As Runtime.InteropServices.COMException
           'MessageBox.Show("HRESULT = 0x" + ex.ErrorCode.ToString("X") + vbCrLf + ex.Message)
       Catch ex As Exception
           LogMessage(\$"Critical error in OnCmd: {ex.ToString()}")
           'MessageBox.Show(\$"PDM Add-in Error: {ex.Message}", "Critical Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
       Finally
           LogMessage("OnCmd EXITED (Finally).")
           ' Do NOT release vault here; it is managed by PDM, not your code.
           If vault IsNot Nothing Then
               Marshal.ReleaseComObject(vault)
           End If
       End Try
   End Sub
#End Region

#Region "Core Logic"
   Private Sub ProcessDrawingFile(ByVal fileAsBaseObject As Object, ByVal parentFolderIdFromCmdData As Integer, ByVal vault As IEdmVault5, ByVal initialPdmFileNameAttempt As String)
       Dim edmFile17 As IEdmFile17 = Nothing
       Dim edmFileFolder As IEdmFolder5 = Nothing
       Dim actualParentFolderIdToUse As Integer = parentFolderIdFromCmdData
       Dim pdmDrawingFileName As String = initialPdmFileNameAttempt
       Dim localDrawingFilePath As String = ""

       Try
           LogMessage(\$"ProcessDrawingFile for PDM file (initial name attempt): {initialPdmFileNameAttempt}. Initial CmdData.ParentFolderID: {parentFolderIdFromCmdData}")

           Try
               edmFile17 = TryCast(fileAsBaseObject, IEdmFile17)
               If edmFile17 IsNot Nothing Then
                   pdmDrawingFileName = edmFile17.Name
                   LogMessage(\$"Successfully cast to IEdmFile17: {pdmDrawingFileName}.")
                   Try
                       edmFileFolder = TryCast(edmFile17.Folder, IEdmFolder5)
                       If edmFileFolder IsNot Nothing Then
                           actualParentFolderIdToUse = edmFileFolder.ID
                           LogMessage(\$"Using ParentFolderID from IEdmFile17.Folder: {actualParentFolderIdToUse} (Name: '{edmFileFolder.Name}')")
                       Else
                           LogMessage(\$"IEdmFile17.Folder was Nothing. Using CmdData.ParentFolderID: {parentFolderIdFromCmdData}")
                           actualParentFolderIdToUse = parentFolderIdFromCmdData
                       End If
                   Catch exMissing As MissingMemberException
                       LogMessage(\$"MissingMemberException for IEdmFile17.Folder: {exMissing.Message}. Interop issue. Using CmdData.ParentFolderID: {parentFolderIdFromCmdData}")
                       actualParentFolderIdToUse = parentFolderIdFromCmdData
                   Catch exFolder As Exception
                       LogMessage(\$"Exception on IEdmFile17.Folder: {exFolder.Message}. Using CmdData.ParentFolderID: {parentFolderIdFromCmdData}")
                       actualParentFolderIdToUse = parentFolderIdFromCmdData
                   End Try
               Else
                   LogMessage(\$"Could not cast base file object to IEdmFile17. Using initial name '{initialPdmFileNameAttempt}' and CmdData.ParentFolderID.")
                   actualParentFolderIdToUse = parentFolderIdFromCmdData
               End If
           Catch castEx As Exception
               LogMessage(\$"Exception casting to IEdmFile17 or accessing its members: {castEx.Message}. Using initial values.")
               actualParentFolderIdToUse = parentFolderIdFromCmdData
           End Try

           ' Always try to get a valid folder ID for the file
           If edmFile17 IsNot Nothing Then
               Dim edmFile5 As IEdmFile5 = TryCast(edmFile17, IEdmFile5)
               If edmFile5 IsNot Nothing Then
                   Dim foundFolderId = GetValidFolderIdForFile(edmFile5, vault)
                   If foundFolderId <> 0 Then
                       actualParentFolderIdToUse = foundFolderId
                       LogMessage(\$"Found valid folder ID for file: {actualParentFolderIdToUse}")
                   Else
                       LogMessage("Could not find a valid folder for the file. Using CmdData.ParentFolderID: " & parentFolderIdFromCmdData)
                       actualParentFolderIdToUse = parentFolderIdFromCmdData
                   End If
               End If
           End If

           If Not pdmDrawingFileName.ToUpper().EndsWith(".SLDDRW") Then
               LogMessage(\$"PDM File '{pdmDrawingFileName}' is not SLDDRW. Skipping.")
               Return
           End If

           Dim drawingFileNameWithoutExtension As String = Path.GetFileNameWithoutExtension(pdmDrawingFileName)

           If USE_HARDCODED_SLDDRW_PATH Then
               localDrawingFilePath = HARDCODED_SLDDRW_PATH
               LogMessage(\$"USING HARDCODED SLDDRW PATH: {localDrawingFilePath}")
               If Path.GetFileName(HARDCODED_SLDDRW_PATH).ToUpper() <> pdmDrawingFileName.ToUpper() Then
                   LogMessage(\$"WARNING: Hardcoded file name '{Path.GetFileName(HARDCODED_SLDDRW_PATH)}' differs from PDM file name '{pdmDrawingFileName}'.")
               End If
               If Not File.Exists(localDrawingFilePath) Then
                   LogMessage(\$"CRITICAL: Hardcoded SLDDRW file does not exist: {localDrawingFilePath}. Cannot convert to PDF.")
                   'MessageBox.Show(\$"Hardcoded SLDDRW file not found: {localDrawingFilePath}", "File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error)
                   Return
               End If
           ElseIf edmFile17 IsNot Nothing Then
               LogMessage(\$"Attempting PDM GetLocalPath for '{pdmDrawingFileName}' using ParentFolderID: {actualParentFolderIdToUse}.")
               Try
                   localDrawingFilePath = edmFile17.GetLocalPath(actualParentFolderIdToUse)
                   If String.IsNullOrEmpty(localDrawingFilePath) OrElse Not File.Exists(localDrawingFilePath) Then
                       LogMessage(\$"GetLocalPath failed or path invalid: '{localDrawingFilePath}'. Attempting GetSpecificVersions.")
                       Dim ppoFiles(0) As EdmSelItem
                       ppoFiles(0).mlDocID = edmFile17.ID
                       ppoFiles(0).mlProjID = actualParentFolderIdToUse
                       vault.GetSpecificVersions(1, ppoFiles, IntPtr.Zero, EdmGetCmdFlags.Egcf_Nothing)
                       localDrawingFilePath = edmFile17.GetLocalPath(actualParentFolderIdToUse)
                       If String.IsNullOrEmpty(localDrawingFilePath) OrElse Not File.Exists(localDrawingFilePath) Then
                           LogMessage(\$"GetLocalPath still failed after GetSpecificVersions: '{localDrawingFilePath}'. Cannot convert.")
                           'MessageBox.Show(\$"Could not get PDM local path for '{pdmDrawingFileName}'.", "PDM Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                           Return
                       End If
                   End If
                   LogMessage(\$"PDM GetLocalPath successful: {localDrawingFilePath}")
               Catch exPath As Exception
                   LogMessage(\$"Exception during PDM GetLocalPath for '{pdmDrawingFileName}': {exPath.Message}. Cannot convert.")
                   'MessageBox.Show(\$"Error getting PDM local path for '{pdmDrawingFileName}': {exPath.Message}", "PDM Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                   Return
               End Try
           Else
               LogMessage(\$"Cannot get local path: IEdmFile17 object is null (or cast failed) and not using hardcoded path. Cannot convert.")
               'MessageBox.Show(\$"Could not obtain IEdmFile17 object to get path for '{pdmDrawingFileName}'. Check COM references for EPDMLibLib and ensure PDM client is working.", "Internal Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
               Return
           End If

           Dim drawingSubfolderName As String = GetFolderNameFromDrawing(drawingFileNameWithoutExtension)
           If String.IsNullOrEmpty(drawingSubfolderName) OrElse drawingSubfolderName.StartsWith("UNKNOWN") Then
               LogMessage(\$"Could not determine folder for '{drawingFileNameWithoutExtension}'. Skipping.")
               'MessageBox.Show(\$"Could not map folder for '{drawingFileNameWithoutExtension}'.", "Folder Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
               Return
           End If

           Dim targetDrawingFolderPath As String = Path.Combine(DRAWINGS_BASE_PATH, drawingSubfolderName)
           Dim targetArchiveFolderPath As String = Path.Combine(ARCHIVE_BASE_PATH, drawingSubfolderName)

           Try
               If Not Directory.Exists(DRAWINGS_BASE_PATH) Then LogMessageAndThrow("Base drawing path missing.", DRAWINGS_BASE_PATH)
               If Not Directory.Exists(ARCHIVE_BASE_PATH) Then LogMessageAndThrow("Base archive path missing.", ARCHIVE_BASE_PATH)
               If Not Directory.Exists(targetDrawingFolderPath) Then Directory.CreateDirectory(targetDrawingFolderPath)
               If Not Directory.Exists(targetArchiveFolderPath) Then Directory.CreateDirectory(targetArchiveFolderPath)
               LogMessage(\$"Directories ensured: Drawings='{targetDrawingFolderPath}', Archive='{targetArchiveFolderPath}'")
           Catch dirEx As Exception
               LogMessage(\$"Error creating directories: {dirEx.Message}")
               'MessageBox.Show(\$"Error creating directories: {dirEx.Message}", "Dir Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
               Return
           End Try

           Dim oldPdfPathInDrawingFolder As String = Path.Combine(targetDrawingFolderPath, drawingFileNameWithoutExtension & ".pdf")
           Dim revision As String = "0"
           Dim enumVar As IEdmEnumeratorVariable5 = Nothing
           If edmFile17 IsNot Nothing Then
               Try
                   enumVar = TryCast(edmFile17.GetEnumeratorVariable(), IEdmEnumeratorVariable5)
                   If enumVar IsNot Nothing Then
                       Dim revisionObj As Object = Nothing
                       If enumVar.GetVar(REVISION_PROPERTY_NAME, "@", revisionObj) AndAlso revisionObj IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(revisionObj.ToString()) Then
                           revision = revisionObj.ToString().Trim()
                       ElseIf enumVar.GetVar(REVISION_PROPERTY_NAME, "", revisionObj) AndAlso revisionObj IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(revisionObj.ToString()) Then
                           revision = revisionObj.ToString().Trim()
                       Else
                           LogMessage(\$"Revision var '{REVISION_PROPERTY_NAME}' empty/not found for '{pdmDrawingFileName}'. Default: '{revision}'.")
                       End If
                       LogMessage(\$"Revision for '{pdmDrawingFileName}': '{revision}'.")
                   Else
                       LogMessage(\$"IEdmEnumeratorVariable5 null for '{pdmDrawingFileName}'. Default revision: '{revision}'.")
                   End If
               Catch revEx As Exception
                   LogMessage(\$"Error getting revision for '{pdmDrawingFileName}': {revEx.ToString()}. Default: '{revision}'.")
               Finally
                   If enumVar IsNot Nothing Then
                       Marshal.ReleaseComObject(enumVar)
                       enumVar = Nothing ' Good practice
                   End If
               End Try
           Else
               LogMessage(\$"edmFile17 is null, cannot get revision. Default: '{revision}'.")
           End If

           Dim archivedPdfName As String = \$"{drawingFileNameWithoutExtension}_REV{revision}.pdf"
           Dim archivedPdfPath As String = Path.Combine(targetArchiveFolderPath, archivedPdfName)

           If File.Exists(oldPdfPathInDrawingFolder) Then
               Try
                   If File.Exists(archivedPdfPath) Then
                       Dim count = 1
                       Dim tempBaseName = Path.GetFileNameWithoutExtension(archivedPdfName)
                       Dim tempExt = Path.GetExtension(archivedPdfName)
                       Dim tempArchivedPdfPath = Path.Combine(targetArchiveFolderPath, \$"{tempBaseName}_{count}{tempExt}")
                       While File.Exists(tempArchivedPdfPath)
                           count += 1
                           tempArchivedPdfPath = Path.Combine(targetArchiveFolderPath, \$"{tempBaseName}_{count}{tempExt}")
                       End While
                       archivedPdfPath = tempArchivedPdfPath
                       LogMessage(\$"Archive '{Path.GetFileName(archivedPdfName)}' exists. Saving as '{Path.GetFileName(archivedPdfPath)}'.")
                   End If
                   File.Copy(oldPdfPathInDrawingFolder, archivedPdfPath, True)
                   LogMessage(\$"Archived '{oldPdfPathInDrawingFolder}' to '{archivedPdfPath}'.")
               Catch archiveEx As Exception
                   LogMessage(\$"Error archiving PDF for '{drawingFileNameWithoutExtension}': {archiveEx.ToString()}")
                   'MessageBox.Show(\$"Error archiving PDF: {archiveEx.Message}", "Archive Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
               End Try
           Else
               LogMessage(\$"No existing PDF at '{oldPdfPathInDrawingFolder}' to archive for '{drawingFileNameWithoutExtension}'.")
           End If

           Dim newPdfPath As String = Path.Combine(targetDrawingFolderPath, drawingFileNameWithoutExtension & ".pdf")
           If ConvertSldDrwToPdf(localDrawingFilePath, newPdfPath) Then
               LogMessage(\$"Successfully converted '{pdmDrawingFileName}' (from '{localDrawingFilePath}') to '{newPdfPath}'.")
               Dim successMsg As New StringBuilder()
               successMsg.AppendLine(\$"PDF for '{drawingFileNameWithoutExtension}' created: {newPdfPath}")
               If File.Exists(archivedPdfPath) AndAlso oldPdfPathInDrawingFolder <> archivedPdfPath Then
                   successMsg.AppendLine(\$"Previous version archived: {archivedPdfPath}")
               ElseIf Not File.Exists(oldPdfPathInDrawingFolder) Then
                   successMsg.AppendLine("No previous PDF found to archive.")
               ElseIf File.Exists(oldPdfPathInDrawingFolder) AndAlso Not File.Exists(archivedPdfPath) Then
                   successMsg.AppendLine("Note: Archiving of previous PDF may have failed.")
               End If
               'MessageBox.Show(successMsg.ToString(), "Process Successful", MessageBoxButtons.OK, MessageBoxIcon.Information)
               Try
                   'If File.Exists(newPdfPath) Then System.Diagnostics.Process.Start(newPdfPath)
               Catch openEx As Exception
                   LogMessage(\$"Error auto-opening new PDF '{newPdfPath}': {openEx.Message}")
               End Try
           Else
               LogMessage(\$"Failed to convert '{pdmDrawingFileName}' (from '{localDrawingFilePath}') to PDF.")
               'MessageBox.Show(\$"Failed to convert '{pdmDrawingFileName}' to PDF. Check logs.", "PDF Conversion Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
           End If

       Catch exMain As Exception
           LogMessage(\$"Major exception in ProcessDrawingFile for PDM file '{pdmDrawingFileName}': {exMain.ToString()}")
       Finally
           If edmFileFolder IsNot Nothing Then
               Marshal.ReleaseComObject(edmFileFolder)
               edmFileFolder = Nothing ' Good practice
           End If
           If edmFile17 IsNot Nothing Then
               Marshal.ReleaseComObject(edmFile17)
               edmFile17 = Nothing ' Good practice
           End If
       End Try
   End Sub

   Private Sub LogMessageAndThrow(message As String, pathDetail As String)
       Dim fullMessage = \$"{message} Path: '{pathDetail}'"
       LogMessage(fullMessage)
       'MessageBox.Show(fullMessage, "Configuration Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
       Throw New DirectoryNotFoundException(fullMessage)
   End Sub

   Private Function GetFolderNameFromDrawing(dwgNameWithoutExtension As String) As String
       If String.IsNullOrWhiteSpace(dwgNameWithoutExtension) Then
           LogMessage("GetFolderNameFromDrawing: Input drawing name is null or whitespace.")
           Return "UNKNOWN_FOLDER_EMPTY_NAME"
       End If

       If dwgNameWithoutExtension.Length >= 3 AndAlso dwgNameWithoutExtension.StartsWith("574") Then
           Return "5 MOTORS"
       ElseIf dwgNameWithoutExtension.Length > 0 Then
           Dim firstChar As Char = dwgNameWithoutExtension(0)
           Select Case firstChar
               Case "0"c : Return "0 CUSTOMER INFO"
               Case "1"c : Return "1 COMPLETE FAN"
               Case "2"c : Return "2 INLET-OUTLET"
               Case "3"c : Return "3 HOUSING"
               Case "4"c : Return "4 WHEELS"
               Case "5"c : Return "5 DRIVE TRAIN"
               Case "6"c : Return "6 ACCESSORIES"
               Case "7"c : Return "7 BASE"
               Case "8"c : Return "8 HARDWARE"
               Case "9"c : Return "9 MATERIAL"
               Case Else
                   LogMessage(\$"GetFolderNameFromDrawing: Drawing name '{dwgNameWithoutExtension}' does not match known prefix for folder mapping.")
                   Return "UNKNOWN_FOLDER_UNMATCHED_PREFIX"
           End Select
       Else
           LogMessage(\$"GetFolderNameFromDrawing: Drawing name '{dwgNameWithoutExtension}' is too short for prefix mapping.")
           Return "UNKNOWN_FOLDER_SHORT_NAME"
       End If
   End Function

   Private Function ConvertSldDrwToPdf(ByVal sldDrwFilePath As String, ByVal pdfOutputPath As String) As Boolean
       Dim sldWorksApp As SldWorks = Nothing
       Dim drawingDoc As ModelDoc2 = Nothing
       Dim modelExt As ModelDocExtension = Nothing
       Dim errors As Integer = 0
       Dim warnings As Integer = 0
       Dim success As Boolean = False
       Dim createdNewSwInstance As Boolean = False
       Dim openedByAddin As Boolean = False ' To track if this function opened the document
       Dim docNameForClosing As String = sldDrwFilePath ' <-- Move declaration here

       If conversionInProgress Then
           LogMessage("Another conversion is in progress, skipping")
           Return False
       End If
       conversionInProgress = True

       If String.IsNullOrEmpty(sldDrwFilePath) Then
           LogMessage("ConvertSldDrwToPdf: sldDrwFilePath is null or empty. Cannot convert.")
           Return False
       End If
       If Not File.Exists(sldDrwFilePath) Then
           LogMessage(\$"ConvertSldDrwToPdf: Source SLDDRW file does not exist: '{sldDrwFilePath}'. Cannot convert.")
           Return False
       End If

       Try
           LogMessage(\$"Starting PDF conversion for: {sldDrwFilePath} to {pdfOutputPath}")

           ' Step 1: Get or Create SolidWorks Application Instance
           Try
               sldWorksApp = TryCast(Marshal.GetActiveObject("SldWorks.Application"), SldWorks)
               If sldWorksApp Is Nothing Then
                   Throw New COMException("No active SolidWorks instance found")
               End If
               createdNewSwInstance = False
               LogMessage("Successfully attached to existing SolidWorks instance")
           Catch ex As Exception
               LogMessage(\$"Creating new SolidWorks instance: {ex.Message}")
               Try
                   sldWorksApp = CType(CreateObject("SldWorks.Application"), SldWorks)
                   If sldWorksApp Is Nothing Then
                       LogMessage("Failed to create SolidWorks instance")
                       Return False
                   End If
                   sldWorksApp.Visible = True  ' Changed to True to prevent background crashes
                   createdNewSwInstance = True
                   LogMessage("Created new SolidWorks instance")
               Catch createEx As Exception
                   LogMessage(\$"Failed to create SolidWorks instance: {createEx.Message}")
                   Return False
               End Try
           End Try

           If sldWorksApp Is Nothing Then
               LogMessage("SolidWorks application object is null after attempting to get/create. Cannot proceed.")
               Return False
           End If

           ' At the start of ConvertSldDrwToPdf
           If createdNewSwInstance Then
               sldWorksApp.CommandInProgress = True ' Prevent other operations
           End If

           ' Step 2: Open the Drawing Document
           Dim alreadyOpenDoc As ModelDoc2 = sldWorksApp.GetOpenDocumentByName(sldDrwFilePath)

           If alreadyOpenDoc IsNot Nothing Then
               LogMessage("Drawing is already open in SolidWorks. Using existing document reference.")
               drawingDoc = alreadyOpenDoc
               openedByAddin = False ' We didn't open it, so we shouldn't close it
           Else
               LogMessage(\$"Opening drawing: {sldDrwFilePath}")
               Dim openErrors As Integer = 0
               Dim openWarnings As Integer = 0
               drawingDoc = CType(sldWorksApp.OpenDoc6(sldDrwFilePath,
                                                       swDocumentTypes_e.swDocDRAWING,
                                                       swOpenDocOptions_e.swOpenDocOptions_Silent Or swOpenDocOptions_e.swOpenDocOptions_ReadOnly,
                                                       "", openErrors, openWarnings), ModelDoc2)
               If drawingDoc IsNot Nothing Then
                   LogMessage(\$"Drawing opened successfully by add-in. SW OpenDoc Errors: {openErrors} ({GetOpenErrorDescription(openErrors)}), Warnings: {openWarnings} ({GetOpenWarningDescription(openWarnings)})")
                   openedByAddin = True ' We opened it, so we are responsible for closing it
                   docNameForClosing = drawingDoc.GetPathName() ' Get the exact path name from SW
                   If String.IsNullOrEmpty(docNameForClosing) Then docNameForClosing = sldDrwFilePath
               Else
                   LogMessage(\$"Failed to open drawing '{sldDrwFilePath}'. SW OpenDoc Errors: {openErrors} ({GetOpenErrorDescription(openErrors)}), Warnings: {openWarnings} ({GetOpenWarningDescription(openWarnings)})")
                   ' No need to return false yet, finally block will handle SW app release
               End If
           End If

           ' Step 3: Process the Document if Opened/Found
           If drawingDoc IsNot Nothing Then
               ' Verify document is fully loaded
               If drawingDoc.GetSaveFlag() Then
                   LogMessage("Document is in an unsaved state, waiting...")
                   System.Threading.Thread.Sleep(1000)
               End If

               modelExt = CType(drawingDoc.Extension, ModelDocExtension)
               If modelExt Is Nothing Then
                   LogMessage("Failed to get ModelDocExtension from the drawing. Cannot save as PDF.")
               Else
                   Dim outputDir As String = Path.GetDirectoryName(pdfOutputPath)
                   If Not Directory.Exists(outputDir) Then
                       Try
                           Directory.CreateDirectory(outputDir)
                           LogMessage(\$"Created output directory: {outputDir}")
                       Catch dirEx As Exception
                           LogMessage(\$"Error creating output directory '{outputDir}': {dirEx.Message}. Cannot save PDF.")
                           success = False ' Mark as failed, proceed to cleanup
                       End Try
                   End If

                   If success OrElse Directory.Exists(outputDir) Then ' Proceed if directory exists or was created
                       If File.Exists(pdfOutputPath) Then
                           Try
                               File.Delete(pdfOutputPath)
                               LogMessage(\$"Deleted existing PDF at: {pdfOutputPath}")
                           Catch delEx As Exception
                               LogMessage(\$"Could not delete existing PDF '{pdfOutputPath}': {delEx.Message}. SaveAs might overwrite or fail.")
                           End Try
                       End If

                       LogMessage(\$"Attempting to save as PDF: {pdfOutputPath}")
                       Dim saveErrors As Integer = 0
                       Dim saveWarnings As Integer = 0
                       success = modelExt.SaveAs(pdfOutputPath,
                                                 swSaveAsVersion_e.swSaveAsCurrentVersion,
                                                 swSaveAsOptions_e.swSaveAsOptions_Silent Or swSaveAsOptions_e.swSaveAsOptions_Copy,
                                                 Nothing, saveErrors, saveWarnings)

                       If success Then
                           LogMessage(\$"Successfully saved PDF. SW SaveAs Errors: {saveErrors} ({GetSaveErrorDescription(saveErrors)}), Warnings: {saveWarnings} ({GetOpenWarningDescription(saveWarnings)})")
                       Else
                           LogMessage(\$"Failed to save PDF (SaveAs returned false). SW SaveAs Errors: {saveErrors} ({GetSaveErrorDescription(saveErrors)}), Warnings: {saveWarnings} ({GetOpenWarningDescription(saveWarnings)})")
                       End If
                   End If ' End if Directory.Exists
               End If ' End if modelExt is not nothing
           Else
               LogMessage(\$"Drawing document was not available for '{sldDrwFilePath}'. PDF conversion skipped.")
               success = False
           End If

       Catch ex As Exception
           LogMessage(\$"CRITICAL EXCEPTION in ConvertSldDrwToPdf: {ex.ToString()}")
           success = False
       Finally
           LogMessage("ConvertSldDrwToPdf: Entering Finally block for cleanup.")

           If modelExt IsNot Nothing Then
               Try
                   Marshal.ReleaseComObject(modelExt)
                   LogMessage("Released ModelDocExtension.")
               Catch exRCO As Exception
                   LogMessage(\$"Error releasing ModelDocExtension: {exRCO.Message}")
               End Try
               modelExt = Nothing
           End If

           If drawingDoc IsNot Nothing Then
               If openedByAddin Then
                   Try
                       ' Give SW a moment to finish any operations
                       System.Threading.Thread.Sleep(1000)

                       If sldWorksApp IsNot Nothing Then
                           ' Don't force close if document is dirty
                           If Not drawingDoc.GetSaveFlag() Then
                               sldWorksApp.CloseDoc(docNameForClosing)
                               LogMessage(\$"Closed document: {docNameForClosing}")
                           Else
                               LogMessage("Document has unsaved changes, skipping close")
                           End If
                       End If
                   Catch ex As Exception
                       LogMessage(\$"Error closing document: {ex.Message}")
                   End Try
               End If

               Try
                   Marshal.ReleaseComObject(drawingDoc)
                   drawingDoc = Nothing
               Catch ex As Exception
                   LogMessage(\$"Error releasing drawingDoc: {ex.Message}")
               End Try
           End If

           If sldWorksApp IsNot Nothing Then
               If createdNewSwInstance Then
                   Try
                       ' Give SW time to finish operations
                       System.Threading.Thread.Sleep(2000)

                       ' Don't exit if there are open documents
                       Dim openDocs As Object = sldWorksApp.GetDocuments()
                       If openDocs Is Nothing OrElse CType(openDocs, Object()).Length = 0 Then
                           sldWorksApp.ExitApp()
                           LogMessage("Exited SolidWorks instance")
                       Else
                           LogMessage("SolidWorks has open documents, skipping exit")
                       End If
                   Catch ex As Exception
                       LogMessage(\$"Error during SolidWorks cleanup: {ex.Message}")
                   Finally
                       Try
                           Marshal.ReleaseComObject(sldWorksApp)
                           sldWorksApp = Nothing
                       Catch ex As Exception
                           LogMessage(\$"Error releasing SolidWorks object: {ex.Message}")
                       End Try
                   End Try
               Else
                   LogMessage("SolidWorks instance was pre-existing, not exiting it from add-in.")
               End If

               If createdNewSwInstance Then
                   GC.Collect()
                   GC.WaitForPendingFinalizers()
                   LogMessage("GC.Collect and GC.WaitForPendingFinalizers called after releasing created SW instance.")
               End If
           End If

           conversionInProgress = False
           LogMessage("ConvertSldDrwToPdf: Exiting Finally block.")
       End Try
       Return success
   End Function

   ' Helper function for SaveAs errors (stub - enhance as needed)
   Private Function GetSaveErrorDescription(errorCode As Integer) As String
       If errorCode = 0 Then Return "No error."
       ' You might need to find the correct enum for SolidWorks save errors
       ' For example, if it was swFileSaveError_e:
       ' Try
       ' Return CType(errorCode, swFileSaveError_e).ToString()
       ' Catch
       ' Return \$"Unknown SolidWorks file save error code (cast failed): {errorCode}"
       ' End Try
       Return \$"SolidWorks SaveAs Error Code: {errorCode}"
   End Function

   ' Helper function for OpenDoc6 errors
   Private Function GetOpenErrorDescription(errorCode As Integer) As String
       If errorCode = 0 Then Return "No error."
       Try
           Return CType(errorCode, swFileLoadError_e).ToString() ' swFileLoadError_e is a valid enum
       Catch
           Return \$"Unknown SolidWorks file load error code (cast failed): {errorCode}"
       End Try
   End Function

   ' Your existing GetOpenWarningDescription function should remain:
   ' Private Function GetOpenWarningDescription(warningCode As Integer) As String
   '     If warningCode = 0 Then Return "No warning."
   '     Try
   '         Return CType(warningCode, swFileLoadWarning_e).ToString()
   '     Catch
   '         Return \$"Unknown SolidWorks file load warning code: {warningCode}"
   '     End Try
   ' End Function
   Private Function GetOpenWarningDescription(warningCode As Integer) As String
       If warningCode = 0 Then Return "No warning."
       Try
           Return CType(warningCode, swFileLoadWarning_e).ToString()
       Catch
           Return \$"Unknown SolidWorks file load warning code: {warningCode}"
       End Try
   End Function

   ' Add this helper function to your class
   Private Function GetValidFolderIdForFile(edmFile As IEdmFile5, vault As IEdmVault5) As Integer
       Dim pos As Object = edmFile.GetFirstFolderPosition()
       If pos IsNot Nothing Then
           Dim folder As IEdmFolder5 = Nothing
           Try
               folder = edmFile.GetNextFolder(pos)
               If folder IsNot Nothing Then
                   Return folder.ID
               End If
           Finally
               If folder IsNot Nothing Then
                   Marshal.ReleaseComObject(folder)
                   folder = Nothing ' Good practice
               End If
           End Try
       End If
       Return 0
   End Function
#End Region

#Region "Logging"
   Private Sub LogMessage(message As String)
       Dim logFilePath As String = ""
       Try
           Dim tempPath As String = Path.GetTempPath()
           If String.IsNullOrEmpty(tempPath) OrElse Not Directory.Exists(tempPath) Then
               tempPath = "C:\Temp" ' Fallback
               If Not Directory.Exists(tempPath) Then Directory.CreateDirectory(tempPath)
           End If
           logFilePath = Path.Combine(tempPath, LOG_FILE_NAME)

           Using writer As StreamWriter = File.AppendText(logFilePath)
               writer.WriteLine(\$"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {message}")
           End Using
       Catch ex As Exception
           System.Diagnostics.Debug.WriteLine(\$"Logging Error to '{logFilePath}': {ex.Message} | Original Msg: {message}")
       End Try
   End Sub
#End Region

End Class