ApprenticeServerComponent replacereference errors.

ApprenticeServerComponent replacereference errors.

AlexFielder
Advisor Advisor
1,830 Views
3 Replies
Message 1 of 4

ApprenticeServerComponent replacereference errors.

AlexFielder
Advisor
Advisor

Hi all,

 

I have the following routine which runs in its own application that is started using Process.start(AppName) from the Inventor ribbonbar:

 

''' <summary>
    ''' Calls our changereference method and includes the path, projectprefix and new folder path.
    ''' </summary>
    ''' <param name="selectedItem"></param>
    Private Sub CopyFiles(selectedItem As String)
        'MessageBox.Show(selectedItem.name + " " + selectedItem.path) '<-debugging
        ChangeReferenceApprentice(selectedItem, NewProject.Prefix, TBNewPath.Text)
        MessageBox.Show("Completed copy design")
        'get the existing Inventor application object or start one.
        Dim InventorApp As Inventor.Application = GetApplicationObject()
        If Not InventorApp.Visible = True Then
            InventorApp.Visible = True
        End If
        InventorApp.Documents.Open(newParentDocumentName, True)
    End Sub

    'start of Apprentice Code
    Private Sub ChangeReferenceApprentice(ByVal ParentDocumentName As String, ByVal ProjectPrefix As String, ByVal ProjectPath As String)
        Dim oApprentice As New ApprenticeServerComponent
        ' Open a document.    
        Dim oDoc As ApprenticeServerDocument = oApprentice.Open(ParentDocumentName)
        If oDoc.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
            ChangeDrawingReference(ParentDocumentName, ProjectPrefix, ProjectPath)
        End If
        If oDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
            ChangeAssemblyReference(ParentDocumentName, ProjectPrefix, ProjectPath)
        End If
        If oDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
            MessageBox.Show("This tool is not designed to work with individual Part files.")
            Exit Sub
        End If
    End Sub

Private Sub ChangeAssemblyReference(ByVal ParentDocumentName As String, ByVal projectprefix As String, ByVal ProjectPath As String) Dim oApprentice As New ApprenticeServerComponent ' Open a document. Dim oDoc As ApprenticeServerDocument = oApprentice.Open(ParentDocumentName) For Each oRefFileDesc As FileDescriptor In oDoc.File.ReferencedFileDescriptors If oRefFileDesc.FullFileName.Contains(My.Settings.ContentCentrePath) Then Continue For 'this line should recursively affect sub assemblies and their part files except it doesn't work for drawings currently. If oRefFileDesc.ReferencedFileType = FileTypeEnum.kAssemblyFileType Then ChangeAssemblyReference(oRefFileDesc.FullFileName, projectprefix, ProjectPath) End If Dim oldFilename As String = System.IO.Path.GetFileName(oRefFileDesc.FullFileName) Dim newFilename As String = projectprefix + My.Settings.ProjectDelimiter + oldFilename Dim oldpath As String = System.IO.Path.GetDirectoryName(oRefFileDesc.FullFileName) Dim newfileref As String = ProjectPath + "\" + newFilename 'copy old to new If Not IO.File.Exists(newfileref) Then IO.File.Copy(oRefFileDesc.FullFileName, newfileref) End If ' Replace the reference. oRefFileDesc.ReplaceReference(newfileref) '<- errors here if you open an assembly file referenced by a drawing. Next ' Save the assembly. newParentDocumentName = System.IO.Path.GetFileName(ParentDocumentName) newParentDocumentName = ProjectPath + "\" + projectprefix + My.Settings.ProjectDelimiter + newParentDocumentName oApprentice.FileSaveAs.AddFileToSave(oDoc, newParentDocumentName) oApprentice.FileSaveAs.ExecuteSaveAs() End Sub
Private Sub ChangeDrawingReference(ByVal ParentDocumentName As String, ByVal ProjectPrefix As String, ByVal ProjectPath As String) Dim oApprentice As New ApprenticeServerComponent Dim oDoc As ApprenticeServerDocument = oApprentice.Open(ParentDocumentName) For Each oRefFileDesc As FileDescriptor In oDoc.File.ReferencedFileDescriptors If oRefFileDesc.FullFileName.Contains(My.Settings.ContentCentrePath) Then Continue For 'this line should recursively affect sub assemblies and their part files except it doesn't work for drawings currently.
'commented section If oRefFileDesc.ReferencedFileType = FileTypeEnum.kAssemblyFileType Then ChangeAssemblyReference(oRefFileDesc.FullFileName, ProjectPrefix, ProjectPath) End If
'end commented section Dim oldFilename As String = System.IO.Path.GetFileName(oRefFileDesc.FullFileName) Dim newFilename As String = ProjectPrefix + My.Settings.ProjectDelimiter + oldFilename Dim oldpath As String = System.IO.Path.GetDirectoryName(oRefFileDesc.FullFileName) Dim newfileref As String = ProjectPath + "\" + newFilename 'copy old to new If Not IO.File.Exists(newfileref) Then IO.File.Copy(oRefFileDesc.FullFileName, newfileref) End If ' Replace the reference. oRefFileDesc.ReplaceReference(newfileref) Next ' Save the assembly. newParentDocumentName = System.IO.Path.GetFileName(ParentDocumentName) newParentDocumentName = ProjectPath + "\" + ProjectPrefix + My.Settings.ProjectDelimiter + newParentDocumentName oApprentice.FileSaveAs.AddFileToSave(oDoc, newParentDocumentName) oApprentice.FileSaveAs.ExecuteSaveAs() End Sub Function GetApplicationObject() As Inventor.Application Dim application As Inventor.Application ' Check whether there is an Outlook process running. If Process.GetProcessesByName("OUTLOOK").Count() > 0 Then ' If so, use the GetActiveObject method to obtain the process and cast it to an Application object. application = DirectCast(Marshal.GetActiveObject("Inventor.Application"), Inventor.Application) Else ' If not, create a new instance of Outlook and log on to the default profile. application = CreateObject("Inventor.Application") 'Dim ns As Outlook.NameSpace = application.GetNamespace("MAPI") 'ns.Logon("", "", Missing.Value, Missing.Value) 'ns = Nothing End If ' Return the Outlook Application object. Return application End Function

This routine works fine if I work with an Assembly that contains only parts, and with a drawing it works if I comment out the section in "ChangeDrawingReference" that recursively opens a referenced assembly.

 

The error message you get from the routine when it does error is tantamount to useless.

 

Can anyone offer an insight?

 

Thanks,

 

Alex.

0 Likes
Accepted solutions (2)
1,831 Views
3 Replies
Replies (3)
Message 2 of 4

AlexFielder
Advisor
Advisor
Accepted solution

Hi All,

 

As is commonly the case with this type of thing, a few several cups of tea and a chat with a colleague has helped me to figure out what I was doing wrong.

 

To that end here is my completed code for replacing references:

 

 

 

 

''' <summary>
    ''' Calls our changereference method and includes the path, projectprefix and new folder path.
    ''' </summary>
    ''' <param name="selectedItem">The file the user selected</param>
    Private Sub CopyFiles(selectedItem As String)
        'MessageBox.Show(selectedItem.name + " " + selectedItem.path) '<-debugging
        ProjectPath = TBNewPath.Text
        If selectedItem.EndsWith(".dwg") Then
            GetDrawingReferencedFiles(selectedItem)
            'change the referenced files first
            For Each referencedFile As AssemblyReference In DrawingReferencedFilesList
                ChangeAssemblyReference(referencedFile.OriginalFilename, referencedFile.OriginalFilename)
            Next
            'then the drawing.
            ChangeDrawingReference(selectedItem, selectedItem)
        ElseIf selectedItem.EndsWith(".iam") Then
            ChangeAssemblyReference(selectedItem, selectedItem)
        End If
        'ChangeReferenceApprentice(selectedItem, selectedItem)
        'ChangeReferenceInventor(GetApplicationObject(), selectedItem, selectedItem)
        MessageBox.Show("Completed copy design")
        'get the existing Inventor application object or start one.
        Dim InventorApp As Inventor.Application = GetApplicationObject()
        If Not InventorApp.Visible = True Then
            InventorApp.Visible = True
        End If
        InventorApp.Documents.Open(newParentDocumentName, True)
    End Sub

    Private Sub GetDrawingReferencedFiles(SelectedDrawingName As String)
        Dim oApprentice As New ApprenticeServerComponent
        Dim oDoc As ApprenticeServerDocument = oApprentice.Open(SelectedDrawingName)
        ' Iterate through the references looking for a    
        ' reference to a specific file.    
        Dim oRefFileDesc As ReferencedFileDescriptor
        For Each oRefFileDesc In oDoc.ReferencedFileDescriptors
            Dim tmp As AssemblyReference = New AssemblyReference
            tmp.OriginalFilename = oRefFileDesc.FullFileName
            DrawingReferencedFilesList.Add(tmp)
        Next
        oDoc.Close()
        oApprentice.Close()
        oApprentice = Nothing
    End Sub

    ''' <summary>
    ''' Copied verbatim from the Inventor API help file.
    ''' </summary>
    ''' <param name="ParentAssemblyDocumentName"></param>
    ''' <param name="originalAssemblyFilename"></param>
    Private Sub ChangeAssemblyReference(ByVal ParentAssemblyDocumentName As String, ByVal originalAssemblyFilename As String)
        Dim oApprentice As New ApprenticeServerComponent
        ' Open a document.    
        Dim oDoc As ApprenticeServerDocument = oApprentice.Open(originalAssemblyFilename)
        ' Iterate through the references looking for a    
        ' reference to a specific file.    
        Dim oRefFileDesc As ReferencedFileDescriptor
        For Each oRefFileDesc In oDoc.ReferencedFileDescriptors
            If oRefFileDesc.FullFileName.Contains(My.Settings.ContentCentrePath) Then Continue For
            Dim oldFilename As String = System.IO.Path.GetFileName(oRefFileDesc.FullFileName)
            Dim newFilename As String = NewProject.Prefix + My.Settings.ProjectDelimiter + oldFilename
            Dim oldpath As String = System.IO.Path.GetDirectoryName(oRefFileDesc.FullFileName)
            Dim newfileref As String = ProjectPath + "\" + newFilename
            'copy old to new
            If Not IO.File.Exists(newfileref) Then
                IO.File.Copy(oRefFileDesc.FullFileName, newfileref)
            End If
            Call oRefFileDesc.PutLogicalFileNameUsingFull(newfileref)
            If oRefFileDesc.FullFileName.EndsWith(".iam") Then
                ChangeAssemblyReference(oRefFileDesc.FullFileName, oRefFileDesc.FullFileName)
            End If
        Next
        ' Set a reference to the FileSaveAs object.    
        Dim oFileSaveAs As FileSaveAs = oApprentice.FileSaveAs
        ' Save the assembly.

        If Not IO.Path.GetFileName(originalAssemblyFilename).StartsWith(NewProject.Prefix) Then
            newParentDocumentName = System.IO.Path.GetFileName(ParentAssemblyDocumentName)
            newParentDocumentName = ProjectPath + "\" + NewProject.Prefix + My.Settings.ProjectDelimiter + newParentDocumentName
        Else
            newParentDocumentName = originalAssemblyFilename
        End If
        Call oFileSaveAs.AddFileToSave(oDoc, newParentDocumentName)
        Call oFileSaveAs.ExecuteSaveAs()
        For Each assy As AssemblyReference In DrawingReferencedFilesList
            If assy.OriginalFilename = originalAssemblyFilename Then
                assy.NewFilename = newParentDocumentName
            End If
        Next
        oApprentice.Close()
        oApprentice = Nothing
    End Sub
    ''' <summary>
    ''' Copied verbatim from the Inventor API help file.
    ''' </summary>
    ''' <param name="ParentAssemblyDocumentName"></param>
    ''' <param name="originalAssemblyFilename"></param>
    Private Sub ChangeDrawingReference(ByVal ParentAssemblyDocumentName As String, ByVal originalAssemblyFilename As String)
        Dim oApprentice As New ApprenticeServerComponent
        ' Open a document.    
        Dim oDoc As ApprenticeServerDocument = oApprentice.Open(originalAssemblyFilename)
        ' Iterate through the references looking for a    
        ' reference to a specific file.    
        Dim oRefFileDesc As ReferencedFileDescriptor
        For Each oRefFileDesc In oDoc.ReferencedFileDescriptors
            Dim newfileref As AssemblyReference = (From f As AssemblyReference In DrawingReferencedFilesList
                                                   Where f.OriginalFilename = oRefFileDesc.FullFileName
                                                   Select f).FirstOrDefault()
            If Not newfileref Is Nothing Then
                Call oRefFileDesc.PutLogicalFileNameUsingFull(newfileref.NewFilename)
            End If
        Next
        ' Set a reference to the FileSaveAs object.    
        Dim oFileSaveAs As FileSaveAs = oApprentice.FileSaveAs
        ' Save the assembly.

        If Not IO.Path.GetFileName(originalAssemblyFilename).StartsWith(NewProject.Prefix) Then
            newParentDocumentName = System.IO.Path.GetFileName(ParentAssemblyDocumentName)
            newParentDocumentName = ProjectPath + "\" + NewProject.Prefix + My.Settings.ProjectDelimiter + newParentDocumentName
        Else
            newParentDocumentName = originalAssemblyFilename
        End If
        Call oFileSaveAs.AddFileToSave(oDoc, newParentDocumentName)
        Call oFileSaveAs.ExecuteSaveAs()
        oApprentice.Close()
        oApprentice = Nothing
    End Sub

The trick seemed to be:

 

Open a drawing and get its file references as a list.

Open each of the file references, change their references and update the list with the new filename

Reopen the original drawing and update the reference(s) to the new path.

 

A couple of caveats are that currently the tool doesn't take into account folder structure because it simply flattens the assembly to a single location/subfolder.

 

In many ways this is better than how a user might currently have things set up- especially if the user is working with Vault.

 

Thanks,

 

Alex.

 

PS. I have reverted to using the PutLogicalFilenameUsingFull() method for the replacement- is there a performance cost to doing it this way?

 

0 Likes
Message 3 of 4

Vladimir.Ananyev
Alumni
Alumni
Accepted solution

If your Inventor models include references to OLE files you have to take into account the ApprenticeServerDocument.ReferencedOLEFileDescriptors collection.  You may find useful the source code of the CopyDesign tool that is provided with the Inventor SDK User Tools.  By default it could be found in the following folder:  C:\Users\Public\Documents\Autodesk\Inventor <version>\SDK\UserTools\CopyDesign.

cheers,


Vladimir Ananyev
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 4 of 4

AlexFielder
Advisor
Advisor

Thanks Vladimir, I wish I had seen that SDK example before I started this. Ho hum.

0 Likes