I do have subassembly where i need to run one specific external rule but only in that subassembly. It is usually about 10 parts. So what i do is open each part, and place rule under before save document. If part is changed rule in those parts will run and i no need to worry. My question here is: Is it possible to run rule in that sub assembly and place specific external rule under event triggers - before save documents. If this can be done will save me a lot time. Thank you all in advance.
Solved! Go to Solution.
Solved by GosponZ. Go to Solution.
Solved by WCrihfield. Go to Solution.
Solved by WCrihfield. Go to Solution.
Hi @GosponZ. It sounds like it might be possible, but it also sounds like it might be pretty complicated to achieve. Are you familiar with accessing the 'hidden' iProperty set where the 'local to document' Event Triggers settings are kept? If not, here are a few of the links within my contribution posts that may help you out in that area.
https://knowledge.autodesk.com/community/article/329361
https://knowledge.autodesk.com/community/article/329766
https://knowledge.autodesk.com/community/article/348361
https://knowledge.autodesk.com/community/article/330921
If you still need more help in this project after reviewing these resources, let me know.
If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.
If you want and have time, I would appreciate your Vote(s) for My IDEAS :light_bulb:or you can Explore My CONTRIBUTIONS
Wesley Crihfield
(Not an Autodesk Employee)
Thank you for information. Programming is not my cup of tee, here and there some easy stuff but for this need help. i search and found in 2016 DuduHarel7605 post code and claim it works. unfortunately not on my side. I'm with Inventor 2021. Just need for my external rule
Dim doc As Document
doc = ThisApplication.ActiveDocument
Dim customPropSets As PropertySets
customPropSets = doc.PropertySets
Dim customPropSet As PropertySet
customPropSet = doc.PropertySets.Item("_iLogicEventsRules")
customPropSet.Add("Rule1", "BeforeDocSave0", 700)
I'm don't understand exactly what you want to do. But maybe this blog post is any help to you.
Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Blog: hjalte.nl - github.com
Thanks for answering. OK here is thing. I do have assembly with few subassembly. In one of those subassemblies i need to run one rule. Question is: Can it be done to run rule in that subass'y and place certain rule in event triggers in each part of that subassembly.
What i do is open each part and manually trigger specific rule to before save.
Thank you for look into it.
You have a (sub)assembly and you want to run a rule in that (sub)assembly that starts rules in the parts of that assembly. In that case you could create a rule like this in your (sub)assembly:
iLogicVb.RunRule("PartA:1", "ruleName1")
iLogicVb.RunRule("PartA:2", "ruleName2")
iLogicVb.RunRule("PartA:3", "ruleName3")
iLogicVb.RunRule("PartA:...", "ruleName...")
iLogicVb.RunRule("PartA:N", "ruleNameN")
Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Blog: hjalte.nl - github.com
JelteDeJong No that is not what i need. I need rule that will place another rule from external rules to rules of events. That code i place above somebody claim it works but i'm not sure what i need to set to that code work.
Thank you
Hi @GosponZ.
I think I may understand what you are trying to do now a bit better. It sounds like we may need to coordinate several things here. It sounds like you want a top level rule you can use from your top level assembly. This rule, when ran, will then run a single rule located within a certain sub-assembly. Then that rule at the sub-assembly level, when ran, will attempt to inject a certain specified external rule under the 'Before Save Document' event of the Event Triggers of each of the components (parts only) of that sub-assembly. Does all that sound right?
If you want us to help you create a rule (or multiple rules) to achieve this complex goal, you will need to provide more information. Maybe in the form of a detailed, bulleted list. Or at last answer all the following questions.
The rule you got from that other post and showed above targets the 'active' document, not the documents of components down within a sub-assembly. Although it is possible for it to succeed in some situations, it is also very likely to fail in many other situations. For one thing, if you have never done anything with the Event Triggers in the 'target' document before, either manually or by code, then that 'hidden' property set won't exist yet. That rule would then fail, throwing an error. To avoid that failure/error, you must first check for the existence of this property set, before trying to use it directly, and if it does not exist yet, try to create it. There is also the potential for multiple other problems if there was already another rule listed under that event in that document. If this were true, then both the property name and the PropID specified could each cause an error, because they may have been used by the property specifying that other rule, and property name & PropID needs to be unique. In general, it is highly recommended to have multiple checks included in this process, to avoid the many of the potential errors/problems involved.
Wesley Crihfield
(Not an Autodesk Employee)
Wow that is very detailed explanation. I appreciate for that.
ok let me be a little bit clear. I do not need run rule from top level assembly. It could be run from that subassembly itself. That rule would be used only in that sub and nowhere else.
We need send material like 2 " longer then is on model. Sub-assembly is placed on one drawing sheet, and it has table with width and length kind like tabular drawing. It need only length to be 2" longer and i have created that rule to make me dimension in table longer , but for every part in that sub i have to go and manually add rule to trigger in case if parts change to run rule in those part and have correct information.
After i make components all my parts are measured with external rule to give me with and length. So it measure also those parts which will be in that mentioned sub-assembly but then i have to do it manually to add 2 inches. All my rules are external. This rule that measure parts i called GetSize, and the other that add 2 inches i called add two inches, and it is just true false rule.
I hope i explained my need and if you guys can help it will save me a bit of time in my drawings.
Thank you very much for look into this
Hi @GosponZ. I think I may have something that will work for you now. It is designed to be used as an external rule, and ran while your sub-assembly is the 'active' document. I put the two variables for the rule name and event name right at the top of the code, in case they might ever need to change. Make sure the rule name is correct, before running it. I included lots of comments throughout the code to help you understand what's going on. I created a custom Function and a custom Sub below the main Sub, to help keep the main Sub shorter & cleaner. They are called to run near the end of the main Sub. A Sub just does something, without returning anything, while a Function can also do something, but a Function will always return something. So the custom function is handling the task of trying to find or create the iProperty Set for the Event Triggers, and returns that property set, if any. The custom sub handles the task of searching through that property set for an existing property within the PropID range of that event, and any properties that are found are checked to see if this rule's name is its value. If an existing property is found with this rule as its value, that means this rule has already been added under this event, so it exits that Sub without doing anything else. But if no property is found with this rule as its value, it then creates a new property with the proper name, proper PropID, and this rule as its value. That then causes that rule to show up under that event in that document's Event Triggers dialog.
Here's the rule:
Sub Main
'specify name of external rule to put into Event Triggers:
Dim oRuleName As String = "add two inches"
'specify which event you want this rule to be fired by
'If 'Before Save Document', then this NEEDS to be "BeforeDocSave"
'this will be used as the beginning part of the property's name
Dim oEventName As String = "BeforeDocSave"
'get the 'active' assembly
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition
'start looping through its components
For Each oComp As ComponentOccurrence In oADef.Occurrences
'check if this component represents a Part, if not, skip to next component
If oComp.DefinitionDocumentType <> DocumentTypeEnum.kPartDocumentObject Then Continue For
'get the Part document that this component represents
Dim oPDoc As PartDocument = oComp.Definition.Document
'try to get or create the 'hidden' Event Triggers iProperty Set in that Part (runs Function defined below)
Dim oEventTriggers As PropertySet = GetEventTriggersPropSet(oPDoc)
'make sure that function returned a value, if not exit the rule
If IsNothing(oEventTriggers) Then
MsgBox("The Event Triggers property set could not be found or created. Skipping to next component.", vbCritical, "")
Continue For
End If
'try to put the specified rule into Event Triggers of Part under the specified event
AddRuleToEventTriggers(oEventTriggers, oRuleName, oEventName)
Next
End Sub
Function GetEventTriggersPropSet(oDoc As Document) As PropertySet
Dim oETPropSet As PropertySet
Dim oDefaultName As String = "_iLogicEventsRules"
Dim oDefaultInternalName As String = "{2C540830-0723-455E-A8E2-891722EB4C3E}"
Try
oETPropSet = oDoc.PropertySets.Item(oDefaultName)
Catch
oETPropSet = oDoc.PropertySets.Item("{2C540830-0723-455E-A8E2-891722EB4C3E}")
Catch
oETPropSet = oDoc.PropertySets.Item("iLogicEventsRules") 'in case it has been 'un-hidden'
Catch
'it wasn't found, so create it
oETPropSet = oDoc.PropertySets.Add(oDefaultName, oDefaultInternalName)
End Try
If Not IsNothing(oETPropSet) Then Return oETPropSet
End Function
Sub AddRuleToEventTriggers(oPSet As PropertySet, oRule As String, oEvent As String)
'Property Name needs to START WITH correct text
'PropID needs to be WITHIN propper range for this event
Dim oPropIDMin As Integer = 700
Dim oPropIDMax As Integer = 799
Dim oProp As Inventor.Property
For oPropID As Integer = oPropIDMin To oPropIDMax
Try
'if there is no property at this PropID, it will go to the Catch portion
oProp = oPSet.ItemByPropId(oPropID)
'a property was found, now check if it's value is this rule's name
'use Contains instead of =, because external rule values will start with "file://"
If CStr(oProp.Value).Contains(oRule) Then
MsgBox("This rule is already listed under that event.", , "")
Exit Sub
End If
Catch
' no property found at that PropID, and
' it has't found a property with this rule name as its value
'so...create it, then exit the sub
oProp = oPSet.Add(oRule, oEvent & oPropID, oPropID)
Exit Sub
End Try
Next
End Sub
If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.
If you want and have time, I would appreciate your Vote(s) for My IDEAS :light_bulb:or you can Explore My CONTRIBUTIONS
Wesley Crihfield
(Not an Autodesk Employee)
I have to ask. Rule is working perfect and place rule before save doc, but when i save file it pop up msg that can't find rule in document. Again add 2 inch is external rule. Why is not recognised? I replaced rule name to be exact as you said.
Thanks
I believe I know why it is doing that. I did some local testing and saw a similar message. I had forgotten that when specifying an external rule, it seems to need a little extra text before the rule name before setting it to the value of the property. This is not needed when working with local rules. The extra text is "file://". So, the quickest way to fix this would be to manually open those components, delete this rule from the Event Triggers, then within this rule, simply add "file://" in front of the rule name when you specify the name of an external rule before you run it again. The next longer way to fix the situation would be to alter this rule to have it attempt to find & replace the rule name in the property with the altered rule name.
The longer/proper fix that I am going to implement in my own solutions to make them more dynamic is the following:
I created another little routine to add into the rule that will check if the rule name you specify is a 'local' rule or an 'external' rule, and when it is an external rule, it will automatically add that little extra text to the start of the specified rule name, before it attempts to set it as the value of the property.
Near the end of the main Sub, but just before the following lines:
'try to put the specified rule into Event Triggers of Part under the specified event
AddRuleToEventTriggers(oEventTriggers, oRuleName, oEventName)
Add the following lines:
'if rule is external rule, add "file://" to the start of the name
If RuleIsExternal(oPDoc, oRuleName) Then
oRuleName = "file://" & oRuleName
End If
That will run the custom Function below, that you are about to add.
Then add the following custom Function code on the next line after the "End Sub" of the main sub.
Function RuleIsExternal(oDoc As Document, oRule As String) As Boolean
'check for the rule in the 'active' document, 'local' document, and supplied 'target' document
' if not found, it is assumed to be external
Dim iRule As iLogicRule
Dim oAuto As IiLogicAutomation = iLogicVb.Automation
Try
iRule = oAuto.GetRule(oDoc, oRule)
Catch
iRule = oAuto.GetRule(ThisApplication.ActiveDocument, oRule)
Catch
iRule = oAuto.GetRule(ThisDoc.Document, oRule)
Catch
Return True
End Try
If IsNothing(iRule) Then Return True Else Return False
End Function
It would take a lot of time to explain why, but it is possible that 'ThisDoc.Document', and 'ThisAppliacion.ActiveDocument', and the document being passed to this Function may all be referring to different documents, so it checks all of them to see if the specified rule name is found in any of them. If it is not found in any of them, it then assumes it is an external rule. The Function returns True if it is an external rule, and False if it is a local rule. Then that earlier code which runs this Function, checks the returned value, then applies the extra text to the front of the name when it's True.
Wesley Crihfield
(Not an Autodesk Employee)
Appreciate you time and effort to help me to solve this problem. Now is running without error. I comment those couple line of code .
'if rule is external rule, add "file://" to the start of the name 'If RuleIsExternal(oPDoc, oRuleName) Then ' oRuleName = "file://" & oRuleName 'End If
cause it triplicate 'file:// before rule name. After that rule is working just how supposed to. Thank you very much again.
I hope there is other people that may need so here is whole code
Sub Main 'specify name of external rule to put into Event Triggers: Dim oRuleName As String = "file://ADD TWO INCH" 'specify which event you want this rule to be fired by 'If 'Before Save Document', then this NEEDS to be "BeforeDocSave" 'this will be used as the beginning part of the property's name Dim oEventName As String = "BeforeDocSave" 'get the 'active' assembly Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition 'start looping through its components For Each oComp As ComponentOccurrence In oADef.Occurrences 'check if this component represents a Part, if not, skip to next component If oComp.DefinitionDocumentType <> DocumentTypeEnum.kPartDocumentObject Then Continue For 'get the Part document that this component represents Dim oPDoc As PartDocument = oComp.Definition.Document 'try to get or create the 'hidden' Event Triggers iProperty Set in that Part (runs Function defined below) Dim oEventTriggers As PropertySet = GetEventTriggersPropSet(oPDoc) 'make sure that function returned a value, if not exit the rule If IsNothing(oEventTriggers) Then MsgBox("The Event Triggers property set could not be found or created. Skipping to next component.", vbCritical, "") Continue For End If 'if rule is external rule, add "file://" to the start of the name 'If RuleIsExternal(oPDoc, oRuleName) Then ' oRuleName = "file://" & oRuleName 'End If 'try to put the specified rule into Event Triggers of Part under the specified event AddRuleToEventTriggers(oEventTriggers, oRuleName, oEventName) Next End Sub Function RuleIsExternal(oDoc As Document, oRule As String) As Boolean 'check for the rule in the 'active' document, 'local' document, and supplied 'target' document ' if not found, it is assumed to be external Dim iRule As iLogicRule Dim oAuto As IiLogicAutomation = iLogicVb.Automation Try iRule = oAuto.GetRule(oDoc, oRule) Catch iRule = oAuto.GetRule(ThisApplication.ActiveDocument, oRule) Catch iRule = oAuto.GetRule(ThisDoc.Document, oRule) Catch Return True End Try If IsNothing(iRule) Then Return True Else Return False End Function Function GetEventTriggersPropSet(oDoc As Document) As PropertySet Dim oETPropSet As PropertySet Dim oDefaultName As String = "_iLogicEventsRules" Dim oDefaultInternalName As String = "{2C540830-0723-455E-A8E2-891722EB4C3E}" Try oETPropSet = oDoc.PropertySets.Item(oDefaultName) Catch oETPropSet = oDoc.PropertySets.Item("{2C540830-0723-455E-A8E2-891722EB4C3E}") Catch oETPropSet = oDoc.PropertySets.Item("iLogicEventsRules") 'in case it has been 'un-hidden' Catch 'it wasn't found, so create it oETPropSet = oDoc.PropertySets.Add(oDefaultName, oDefaultInternalName) End Try If Not IsNothing(oETPropSet) Then Return oETPropSet End Function Sub AddRuleToEventTriggers(oPSet As PropertySet, oRule As String, oEvent As String) 'Property Name needs to START WITH correct text 'PropID needs to be WITHIN propper range for this event Dim oPropIDMin As Integer = 700 Dim oPropIDMax As Integer = 799 Dim oProp As Inventor.Property For oPropID As Integer = oPropIDMin To oPropIDMax Try 'if there is no property at this PropID, it will go to the Catch portion oProp = oPSet.ItemByPropId(oPropID) 'a property was found, now check if it's value is this rule's name 'use Contains instead of =, because external rule values will start with "file://" If CStr(oProp.Value).Contains(oRule) Then MsgBox("This rule is already listed under that event.", , "") Exit Sub End If Catch ' no property found at that PropID, and ' it has't found a property with this rule name as its value 'so...create it, then exit the sub oProp = oPSet.Add(oRule, oEvent & oPropID, oPropID) Exit Sub End Try Next End Sub
I've tried this and it seems to work. I get an external rule added to my part. If i right click the rule in the trigger and say open rule, it opens the correct rule. The rule is added under Before Save, yet when i save, the rule does not trigger. When I delete the rule and add it manually and hit save, it still does not trigger. If it start a new unrelated part and add the rule manually it does trigger...
I added a different rule to the stack and then they both triggered. I then removed the rule i added, and the original rule then triggered....so, why doesn't it trigger off the code?
public void AddTrigger()
{
Document pdoc = (Document)Globals._InvApp.ActiveDocument;
string ruleName = @"file://R_BLANK_KG_CM";
string oEventName = "BeforeDocSave";
PropertySet oEventTriggers = GetEventTriggersPropSet(pdoc);
if (oEventTriggers == null)
{
MessageBox.Show("The Event Triggers property set could not be found or created.", "Whoops");
return;
}
//try and add new rule trigger
AddRuleToEventTriggers(oEventTriggers, ruleName, oEventName);
pdoc.Save2(false);
}
public PropertySet GetEventTriggersPropSet(Document pdoc)
{
PropertySet oETPropSet;
string oDefaultName = "_iLogicEventsRules";
string oDefaultInternalName = "{2C540830-0723-455E-A8E2-891722EB4C3E}";
try
{
oETPropSet = pdoc.PropertySets[oDefaultName];
}
catch
{
try
{
//if has been unhidden
oETPropSet = pdoc.PropertySets["iLogicEventsRules"];
}
catch
{
//it wasn't found, so create it
oETPropSet = pdoc.PropertySets.Add(oDefaultName, oDefaultInternalName);
}
}
return oETPropSet;
}
public void AddRuleToEventTriggers(PropertySet oPSet, string oRule, string oEvent)
{
Inventor.Property oProp;
int oPropIDMin = 700;
int oPropIDMax = 799;
for (int i = oPropIDMin; i < oPropIDMax; i++)
{
try
{
oProp = oPSet.ItemByPropId[i];
if (System.Convert.ToString(oProp.Value).Contains(oRule))
{
//rule already exists, end process
break;
}
}
catch
{
oProp = oPSet.Add(oRule, oEvent + i, i);
break;
}
}
//return;
}
Hi @mslosar. I hear reports similar to this every once in a while from others, and I do not know what causes this unexpected behavior. It kind of seems like some sort of document update/rebuild, memory reset, or something similar needs to happen sometimes to clear things up so that this API routine will work properly, but I have not been able to pinpoint the exact process yet. I do know of a couple ways to clear Inventor's/iLogic's memory, but I have not had a chance to test if they would be effective in a case like this, because I simply do not use this process that much, and do not seem to encounter this issue.
You can execute this command to free up iLogic's memory:
ThisApplication.CommandManager.ControlDefinitions.Item("iLogic.FreeILogicMemory").Execute
You can use this line of code to clear Inventor's internal clipboard, which I assume is similar to clearing Inventor's 'session memory':
ThisApplication.CommandManager.ClearPrivateEvents
Another thought might be to record which (if any) properties/rules may already be in the set, then completely delete the property set being used for the Event Triggers, then maybe update the document, then recreate the set, then put the rules back into it as needed, then maybe another document update. Again, I haven't tested to see if that process world work to totally eliminate this issue or not either. Just some thoughts.
Wesley Crihfield
(Not an Autodesk Employee)
Where would you suggest I add those? Or are you suggesting I run it, then run the addin? I don't mind trying it.
As for the part in question, there are no other rules attached to the part i'm trying this on at all.
I simply added a second copy of the same rule as a test, which did nothing. So, I deleted it. I then added another unrelated rule to the trigger at which point both rules worked. I deleted the unrelated one i added and then the original ran. But, there were no there rules in the part at all. No internal rules not being and run and no other rules, period, in any of the triggers.
My entire process was close inventor, update the addin, run inventor open a sample part (i made an ipt of a small rectangular plate) and run the command from the ribbon. I would find it odd that anything would be loaded for ilogic at all at that point aside from loading it when Inventor opens.
I think i may have gotten this. Three successful tries on the sample part anyhow 🙂
When I first wrote the original iLogic version of this based on what I saw on the forum, this issue was brought up and the solution there was adding a new local temporary rule, adding the trigger you really want, and then deleting your temp rule. So, that part dawned on me last night so i tried it this morning and after a couple adjustments for C#, it does seem to work.
public void AddTrigger()
{
Document pdoc = (Document)Globals._InvApp.ActiveDocument;
string iLogicAddinGuid = "{3BDD8D79-2179-4B11-8A5A-257B1C0263AC}";
Inventor.ApplicationAddIn addin = null;
try
{
addin = Globals._InvApp.ApplicationAddIns.get_ItemById(iLogicAddinGuid);
}
catch { }
if (addin != null)
{
if (!addin.Activated)
addin.Activate();
}
dynamic _iLogicAutomation = addin.Automation;
_iLogicAutomation.CallingFromOutside = true;
object newRule = _iLogicAutomation.AddRule(pdoc, "TempRule_392856A1", "");
_iLogicAutomation.RulesOnEventsEnabled = true;
string ruleName = @"file://R_BLANK_KG_CM";
string oEventName = "BeforeDocSave";
PropertySet oEventTriggers = GetEventTriggersPropSet(pdoc);
if (oEventTriggers == null)
{
MessageBox.Show("The Event Triggers property set could not be found or created.", "Whoops");
return;
}
//try and add new rule trigger
AddRuleToEventTriggers(oEventTriggers, ruleName, oEventName);
_iLogicAutomation.DeleteRule(pdoc, "TempRule_392856A1");
pdoc.Save2(false);
}
Can't find what you're looking for? Ask the community or share your knowledge.