Unspecified Error When Attempting To Suppress Component In Subassembly Model State

Unspecified Error When Attempting To Suppress Component In Subassembly Model State

bbhattaraiSZ83G
Participant Participant
377 Views
8 Replies
Message 1 of 9

Unspecified Error When Attempting To Suppress Component In Subassembly Model State

bbhattaraiSZ83G
Participant
Participant

Hi! I keep running into an unspecified error when trying to use this loop to suppress components in a subassembly. I'm having trouble diagnosing the exact issue because the error is unspecified. This is my first time working with Model States using Inventor Programming so I think it may be related to that but I'm not sure. 

So to start, I have this loop in my main() subroutine:

Sub Main()
' Get the assembly component definition
Dim oAsmCompDef As AssemblyComponentDefinition
oAsmCompDef = ThisDoc.ModelDocument.ComponentDefinition

' Loop through each occurrence in the assembly
Dim asmOcc As ComponentOccurrence
Dim asmDoc As Document
For Each asmOcc In oAsmCompDef.Occurrences
	asmDoc = asmOcc.Definition.Document
	
	If asmOcc.DefinitionDocumentType = kAssemblyDocumentObject And asmDoc.IsModifiable = True Then
		
    ' Get the iProperty description of the current occurrence
    Dim occDescription As String = asmOcc.Definition.Document.PropertySets.Item("Design Tracking Properties").Item("Description").Value
	
	If needsSTP(occDescription) Then
		'MsgBox(asmOcc.Name)
		' Create STP model representation, suppress non-pipe features, export assembly
		Call createSTEPModelState(asmOcc)
	
		Dim destinationPath As String = getSTPAddress(IO.Path.GetFileNameWithoutExtension(asmOcc.Definition.Document.FullFileName))
		'MsgBox(destinationPath)
		Call suppressNonPipe(asmOcc)
		
		Call exportAsSTP(asmOcc, destinationPath)
		
		asmOcc.ActiveModelState = "[Primary]"
		
	End If

End If
Next asmOcc
End Sub

The needsSTP function simply compares the description against an array of keywords and identifies if the description contains any of the key words. The getSTPAddress is a helper function that takes the address of the file being examined and creates a save location file address.

createSTEPModelState is the subroutine I'm using to create an alternate Model State for STEP exporting:

Sub createSTEPModelState(ByVal oOcc As ComponentOccurrence)
	Dim oDoc As AssemblyDocument = oOcc.Definition.Document
	Dim oCompDef As AssemblyComponentDefinition = oDoc.ComponentDefinition
	
	Dim oModelStates As ModelStates
	Dim stepState As ModelState
    oModelStates = oDoc.ComponentDefinition.ModelStates
	
	Try
	stepState = oCompDef.ModelStates.Item("STEP")
    oOcc.ActiveModelState = stepState.Name
	Catch
	stepState = oCompDef.ModelStates.Add("STEP")
    oOcc.ActiveModelState = stepState.Name
	End Try
	
End Sub

Lastly, here is the subroutine I'm using to suppress components:

Sub suppressNonPipe(ByVal oOcc As ComponentOccurrence)
	
	If oOcc.ActiveModelState = "STEP" Then
		
		Dim oAsmCompDef As AssemblyComponentDefinition
		oAsmCompDef = oOcc.Definition.Document.ComponentDefinition

' Loop through each occurrence in the assembly
Dim asmOcc As ComponentOccurrence
Dim asmDoc As Document
For Each asmOcc In oAsmCompDef.Occurrences
	asmDoc = asmOcc.Definition.Document
		
    ' Get the iProperty description of the current occurrence
    Dim occDescription As String = asmOcc.Definition.Document.PropertySets.Item("Design Tracking Properties").Item("Description").Value
		Try
			asmOcc.Suppress
		Catch
			MsgBox(asmOcc.Name & " cannot be suppressed!")
		End Try
	
Next asmOcc

	Else
		MsgBox("The model state is not set for STEP files!")
	End If
	
End Sub

I am running into issues with the asmOcc.Suppress line, where I am consistently getting the Catch statement MsgBox. I'm able to create the alternate model state, save as a STEP file, and return to the primary model state just fine, the only issue is with part suppression. The intent of the entire rule is to loop through the subassemblies of a top-level assembly and identify if they need to be exported (hence the needsSTP function), then if so go into that subassembly, create the alternate model state, suppress components not desired for the STEP export (anything without "PIPE" in the description), then export the subassembly as a .STP and return to the original ([Primary]) model state. All of this works for the suppression and I'm not sure why. The files are modifiable and I'm able to manually suppress the components.

0 Likes
378 Views
8 Replies
Replies (8)
Message 2 of 9

C_Haines_ENG
Collaborator
Collaborator

Can you remove the "Try - Catch" aspect of the Suppress line and post the actual error that Inventor gives you?

0 Likes
Message 3 of 9

bbhattaraiSZ83G
Participant
Participant

That's when it gives me the unspecified error -- the Try-Catch is there so that rather than stopping the program entirely it just lets me know that the part couldn't be suppressed. Here's the full error message:

System.Runtime.InteropServices.COMException (0x80004005): Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at Inventor.ComponentOccurrence.Suppress(Boolean SkipDocumentSave)
at ThisRule.suppressNonPipe(ComponentOccurrence oOcc) in external rule: Export STP and DXF (DO NOT USE):line 116
at ThisRule.Main() in external rule: Export STP and DXF (DO NOT USE):line 29
at Autodesk.iLogic.Exec.AppDomExec.ExecRuleInAssembly(Assembly assem)
at iLogic.RuleEvalContainer.ExecRuleEval(String execRule)


0 Likes
Message 4 of 9

C_Haines_ENG
Collaborator
Collaborator

Try running this, I'm starting to believe its more of an access issue. Is it failing on sub assembly components?

 

Sub Main
	
	Dim oAsm As AssemblyDocument = ThisDoc.Document
	
	For Each oOcc As ComponentOccurrence In oAsm.ComponentDefinition.Occurrences.AllLeafOccurrences
		
		oOcc.Suppress
		
	Next
	
End Sub

 

Sometimes its easier to start out simple and see where the issues are. 

0 Likes
Message 5 of 9

bbhattaraiSZ83G
Participant
Participant

Nope, that worked great! It successfully suppressed all my components. Though, if this is relevant, I implemented that code as a local rule right inside one of my subassemblies, whereas the program I'm trying to implement will be a global (external) rule. I'll keep trying to build on that and slowly increment the suppression algorithm to see if I can identify the exact issue. I'll let you know if I come across anything interesting. Thanks for the suggestion! 

0 Likes
Message 6 of 9

bbhattaraiSZ83G
Participant
Participant

Hm, I think the issue has something to do with being in a separate Model State. When I commented out the parts of the larger program (external rule) that set the "STEP" model state and attempted the suppression, they had successfully been suppressed! I verified by importing the .STP files and they looked correct. I just added a separate routine to log and unsuppress all the components after I exported them.

0 Likes
Message 7 of 9

WCrihfield
Mentor
Mentor

Hi guys.  After reading through this discussion, I have another idea about why it may be failing, and a suggestion about a slightly different way of doing things that might work better for you.  It has to do with 'context'.  When accessing lower level components of an assembly component occurrence that represents a sub assembly, there are two ways to do that, with each way having its own 'behavior' (pros & cons).  One way is through the ComponentOccurrence.SubOccurrences property.  The other way is through ComponentOccurrence.Definition.Occurrences.  By the way, the ComponentOccurrence.Definition property gives you the same object (the ComponentDefinition that this occurrence is directly referencing) as the ComponentOccurrence.Definition.Document.ComponentDefinition property does, so that longer route is not necessary.  Anyways, when using the 'SubOccurrences' property, that maintains 'lineage' with the higher level (parent) assembly, and will mean that your code will be working with 'proxies' of the lower level stuff, so that changes may just effect things from the perspective of the higher level assembly, without actually changing the source files themselves.  However, when using the ComponentOccurrence.Definition.Occurrences route, you are actually stepping into that other 'definition' (different context), which breaks that lineage with any parent level assembly(s), and changes made will effect those other source files directly, not just proxies.  Your code seems to be using that second route.

 

(PS:  I believe the ComponentOccurrences.AllLeafOccurrences route also maintains lineage with the higher level assembly(s), who's context (the 'definition' of the main/top assembly) you used that property from.)

 

With that in mind, the second issue that sounds possible here is ModelState related, and that one is much more difficult to explain.  Essentially, you always need to make sure that, when attempting to make 'changes' to another document that has more than just that one original ModelState in it, you are working with the 'factory' version, not a 'member' version.  There will only be a factory when there are 2 or more ModelStates in that 'file'.  When a single file has multiple ModelStates in it, then it can also have multiple Documents defines within it, potentially one for each ModelState.  Which document is the factory document changes when the 'active' ModelState changes, because the factory document is simply the document associated with the currently 'active' ModelState.  And you can only make changes to the factory document in those situations, while the documents associated with the 'other members' will act like ReadOnly.  So, if your code is accessing a 'member' Document, it will be able to 'read' from it, but will not be able to make changes to it.  There are multiple ways to work around this type of situation, depending on the circumstances and what you are trying to do.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 8 of 9

bbhattaraiSZ83G
Participant
Participant

Wow, incredible explanation Wesley! Thanks for taking the time to write that up. The factory document explanation was very very helpful, when looking at previous discussions on programmatically implementing Model States I frequently saw FactoryDocument used but never really understood the difference, so that makes a lot more sense now. Very good to know about the difference between accessing lower-level components as well, as that's something I frequently have to do.

May I ask where you learned about these details? I'm entirely self-taught in Inventor (and OOP in general) so I'd love to be able to have the level of understanding you do.

0 Likes
Message 9 of 9

WCrihfield
Mentor
Mentor

As for where or how I learned stuff like that, it was a long process.  I have had a large portion of my attention on automating Inventor for many years now, and have also been spending a lot of time reading and interacting with others on this Inventor API / iLogic / VBA / add-ins forum for many years now.  This is certainly one of the great places to come to search for existing resources, and ask questions when you can't find exactly what you are looking for.  I am also referencing Inventor's online help documentation a lot, and attending live (or pre-recorded) webinars or zoom meetings online, where other knowledgeable folks are 'teaching' different concepts/tasks/techniques about Inventor.  Some of the other forum folks that have been here for a while have their own personal Blog sites for Inventor related stuff, that contain some pretty helpful resources also.  Another great place to explore is the Autodesk University.  It has entire teaching courses and classes available, with their own downloadable resource files, and on-demand videos of previous classes/courses, so you can follow along.  A major factor has been because I find this stuff very interesting, so it is easily learned from personal exploration, experience, trial & error testing.  So, it was a combination of lots of things over several years.

 

I certainly has my misconceptions about what ModelStates were, and how they worked for quite a while when they first appeared.  Due to the way our Autodesk updates are managed by a corporate IT department, it was nearly a year after the 2022 version of Inventor became available (first version with them) before we got updated to that version.  So, during that time, I was reading about others encounters with them, and the issues they were having in their automation efforts due to their introduction.  They certainly made a lot of automation tasks a lot more complex, and complicated to understand, from a code point of view.  I'm sure I still don't necessarily know everything' about them, but I keep learning as I go, just like everyone else.  Good luck.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes