FileDescriptor.ReplaceReference Not always working

FileDescriptor.ReplaceReference Not always working

jcraig
Enthusiast Enthusiast
473 Views
6 Replies
Message 1 of 7

FileDescriptor.ReplaceReference Not always working

jcraig
Enthusiast
Enthusiast

I am migrating my current add in that was developed for 2020 and 2021 to version 2025. As expected some issues have reared their head in this process. This one in particular is not allowing me to debug the failure of the method.

 

We have configurable assemblies. To start a new assembly I have a bit of code that creates a copy of an existing configurable assembly, using system.io.file.copy same as copying in windows explorer. This copies all of the files. The assembly and the parts and subassemblies in the main assembly. After the copy the files are renamed to make them unique. Once this is completed I need to iterate thru the assembly to replace the file references for all of the components, parts and subassemblies and parts in the subassemblies. . . to make the assembly point to the new components.

 

Below is the code for updating the assembly component references to point to the new files. This is a recursive sub when it comes to subassemblies.

 

    Private Sub UpdateAssemblyPartReferences(asmDef As Inventor.AssemblyComponentDefinition, level As Integer)
        Dim increment As Double
        increment = Math.Floor(100 / asmDef.Occurrences.Count)
        ProgressBar2.Value = ProgressBar2.Minimum
        For Each CompOcc As Inventor.ComponentOccurrence In asmDef.Occurrences
            Dim compDef As Inventor.ComponentDefinition
            compDef = CompOcc.Definition
            Dim compDoc As Inventor.Document
            compDoc = compDef.Document
            If compDoc.DocumentType = Inventor.DocumentTypeEnum.kAssemblyDocumentObject Then
                Dim ReplacedAssemRef As Boolean
                ReplacedAssemRef = replaceFileRef(CompOcc)
                If ReplacedAssemRef Then 'replace the subassembly subcomponents if the subassembly reference was replaced.
                    Dim AsmDoc As Inventor.AssemblyDocument
                    'redefine the compdoc here after the compOcc has been redefined
                    compDoc = CompOcc.Definition.Document
                    'AsmDoc = ThisApplication.Documents.Open(compDoc.File.FullFileName)
                    AsmDoc = compDoc
                    Dim subAssemCompDef As Inventor.AssemblyComponentDefinition
                    subAssemCompDef = AsmDoc.ComponentDefinition
                    UpdateAssemblyPartReferences(subAssemCompDef, 2)
                    'AsmDoc.Close(False)
                End If
            ElseIf compDoc.DocumentType = Inventor.DocumentTypeEnum.kPartDocumentObject Then
                replaceFileRef(CompOcc)
            End If
            If level = 1 Then
                ProgressBarIncrement(ProgressBar1, increment)
                Me.Refresh()
            Else
                ProgressBarIncrement(ProgressBar2, increment)
                Me.Refresh()
            End If
        Next
    End Sub

 

Here is the code that actually replaces the file references. 

    Private Function replaceFileRef(CompOcc As Inventor.ComponentOccurrence) As Boolean ' will return true if the componenet file reference was replaced. Will return false otherwise.
        Dim FileDisc As Inventor.FileDescriptor
        FileDisc = CompOcc.ReferencedDocumentDescriptor.ReferencedFileDescriptor
        Dim curFileName As String
        Dim newFileName As String
        curFileName = FileDisc.FullFileName

        Dim SerialNumStr As String
        SerialNumStr = SerialNum & "_"
        If InStr(curFileName, "\SO-") > 0 Then
            Dim curFileNameRelPath As String = curFileName.Substring(ConfigPath.Length)
            newFileName = vesselPath & curFileNameRelPath.Replace("\SO-", "\" & SerialNumStr)
            If System.IO.File.Exists(newFileName) Then
                Try
                    FileDisc.ReplaceReference(newFileName)
                    If FileDisc.FullFileName = newFileName Then
                        Return True
                    Else
                        MsgBox(FileDisc.FullFileName & " was not changed to " & newFileName, vbOKOnly, "Error replacing file")
                        Return False
                    End If

                Catch ex As Exception
                    MsgBox(FileDisc.FullFileName & ": " & ex.Message & " : " & ex.StackTrace, vbOKOnly, "Error replacing file")
                End Try

                Exit Function
            End If
        End If
        Return False
    End Function

 

The issue is that in 2025 the top level components file references are successfully replaced. However the components in the subassemblies are not successfully replaced.

 

The line FileDisc.ReplaceReference(newFileName) is being ran. No error is being thrown. But the file reference is not replaced on subassembly components only. Top level assembly components are being appropriately replaced.

 

Any insight as to why this is happening in 2025 and it worked fine in 2021.

 

Thanks in advance.

Accepted solutions (2)
474 Views
6 Replies
Replies (6)
Message 2 of 7

mr_ensing
Advocate
Advocate

Only thing i have to offer, is that comparing strings like that might not be the way: 

	If FileDisc.FullFileName = newFileName Then
		Return True
	Else

 Probably better to use String.Compare. Your code might return some false True conditions.

0 Likes
Message 3 of 7

jcraig
Enthusiast
Enthusiast

@mr_ensing, Thanks for the suggestion. I will make that change. however that is not what is causing the issue. The issue was present prior to me adding this bit of diagnostic code to attempt to figure out what was going on. 

 

So far the comparison has been reliable enough and has thrown the msgbox when the replacement did not complete correctly and does not throw it when it does replace it correctly.

 

Thanks again for the suggestion.

 

0 Likes
Message 4 of 7

WCrihfield
Mentor
Mentor
Accepted solution

Hi @jcraig.  Maybe as part of your debug process, you can add in the Document.IsModifiable check.  When jumping from 2020 & 2021, to 2025, you now have to deal with ModelStates, which tends to greatly complicate a lot of tasks that we attempt to do by code.  If any of your documents had any LevelOfDetailRepresentations in them, those got automatically converted to a ModelState when migrated into 2022 or later version of Inventor.  Once that happens, there can be multiple Document references within one file on disk.  Also, when there are multiple ModelStates in a model document, you can only make changes to the 'factory' version Document, which is the Document that is associated with the 'active' ModelState in that file.  There may also be a Document associated with the other ModelStates in that file, but those other documents will act like ReadOnly from a code point of view.  So, in order to make changes to the other ModelState 'member' documents, you must do one of the possible workaround processes.  One option is to set the ModelStateEditScope to 'factory scope or all members scope', instead of active member scope, before making the changes.  Another strategy, is to iterate through the ModelStates, activate each one, make changes to that version Document, then move on to the next version.  Or make the changes within the ModelStateTable, either though the built-in dialog, or in Excel.  Some of those processes are more complex than others.

 

In an assembly, when you insert a component occurrence, and that occurrence is set to a specific ModelState, and there are multiple ModelStates in the document it is referencing, that referenced document will be interpreted as a ModelState 'member' document.  If there are two (or more) occurrences in your assembly that reference the same 'File on disk', but different ModelStates, your code process may be able to 'change/edit/write' to the 'first' occurrence it encounters, but then it will not be able to 'change/edit/write' to the next (or subsequent) occurrences that are set to other ModelStates, without first updating the assembly.  Just another complication thrown in there.

 

Also, if any of your occurrences are suppressed, then accessing its Definition property will throw an error, so checking if it is suppressed is a good idea, before accessing its definition.  Then, there are some Types of definitions (such as 'virtual' or 'welds') where there will not be a Document associated with them, so that sometimes also needs to be filtered for.  When comparing two Strings, another small trick is to use the .ToUpper function on both Strings, to avoid capitalization differences throwing the results off.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 7

jcraig
Enthusiast
Enthusiast

@WCrihfield 

 

I was suspicious if it had something to do with the model states. I have already ran into the situation where updating iProperties only updates some iProperties in some of the model states. Very hit and miss as some iProperties are updated across all model states but others are not. 

 

I will test some of the mentioned techniques below and I will let you know what I find. 

0 Likes
Message 6 of 7

mr_ensing
Advocate
Advocate
Model states, figures.
At some point I have to deal with several model state induced problems.
Thanks for the writeup, very helpful.
0 Likes
Message 7 of 7

jcraig
Enthusiast
Enthusiast
Accepted solution

So following up on this. Not sure what was the official fix. I went thru and copied all of the automatically created Model States that were created from my LOD reps. I then deleted the automatically created Model States and left only the copy. This was to fix up BOM issues. I also changed the configured LOD (err. . . I mean Model State) to point to the "Default" model state in the subassemblies. This still would not work with the FileDescriptor.ReplaceFileReference() code.

 

I wound up changing to ComponentOccurrence.Replace() instead. This does work after making the other changes.

    Private Function replaceFileRef(CompOcc As Inventor.ComponentOccurrence) As Boolean ' will return true if the componenet file reference was replaced. Will return false otherwise.
        Dim FileDisc As Inventor.FileDescriptor
        FileDisc = CompOcc.ReferencedDocumentDescriptor.ReferencedFileDescriptor
        Dim curFileName As String
        Dim newFileName As String
        curFileName = FileDisc.FullFileName

        Dim SerialNumStr As String
        SerialNumStr = SerialNum & "_"
        If InStr(curFileName, "\SO-") > 0 Then
            Dim curFileNameRelPath As String = curFileName.Substring(ConfigPath.Length)
            newFileName = vesselPath & curFileNameRelPath.Replace("\SO-", "\" & SerialNumStr)
            If System.IO.File.Exists(newFileName) Then
                Try
                    CompOcc.Replace(newFileName, False)
                    'FileDisc.ReplaceReference(newFileName)
                    FileDisc = CompOcc.ReferencedDocumentDescriptor.ReferencedFileDescriptor
                    If FileDisc.FullFileName = newFileName Then
                        Return True
                    Else
                        MsgBox(FileDisc.FullFileName & " was not changed to " & newFileName, vbOKOnly, "Error replacing file")
                        Return False
                    End If

                Catch ex As Exception
                    MsgBox(FileDisc.FullFileName & ": " & ex.Message & " : " & ex.StackTrace, vbOKOnly, "Error replacing file")
                End Try

                Exit Function
            End If
        End If
        Return False
    End Function


I did use the 

AsmDef.ModelStates.MemberEditScope = Inventor.MemberEditScopeEnum.kEditAllMembers

to update the iProperties for all model states. 

 

Thanks for the input. I hope this helps someone down the line.