How to use iLogic in AddIn

How to use iLogic in AddIn

PolemEngineering
Advocate Advocate
851 Views
13 Replies
Message 1 of 14

How to use iLogic in AddIn

PolemEngineering
Advocate
Advocate

I am looking for a way to create a few variables (including the Vault database logged in to) at the start of an Inventor session, which will be kept up to date during the session based on some event handlers (already functional in an iLogic-rule). These values ​​are important because they determine whether triggered rules can be run or not. I want to avoid having to set this value over and over again, because it causes a noticeable delay for larger assemblies.

 

This must probably be an add-in, as iLogic doesn't seem to become functional until the first document is available. I have added references to several iLogic libraries.

Furthermore I thought the following should work, but apparently I lack some knowledge of VB.net. It's just a MyCode.addin and a StandardAddInServer.vb

 

 

 

Public Class StandardAddInServer
    Implements Inventor.ApplicationAddInServer
    'Application events object
    Private WithEvents MyAppEvents As ApplicationEvents
    Public ReadOnly SharedVariable As ISharedVariable

Public Sub Activate(AddInSiteObject As ApplicationAddInSite, FirstTime As Boolean) Implements ApplicationAddInServer.Activate

    MessageBox.Show("At the beginning of ApplicationAddInServer.Activate")
    If Not SharedVariable.Exists("ActiveDatabase") Then
        SharedVariable("ActiveDatabase") = "Test"
    End If
    MessageBox.Show("At the end of ApplicationAddInServer.Activate")

End Sub
End Class

 

 

 

 AddIn is loaded. Messageboxes are shown. How to correctly approach the ISharedVaribale interface is a mystery to me.

 

Can someone give me a push in the right direction?

Thanks!

 

René van der Starre

0 Likes
Accepted solutions (1)
852 Views
13 Replies
Replies (13)
Message 2 of 14

m_baczewski
Advocate
Advocate

@PolemEngineering 

Hello,

 

I recommend using the tutorials created by @JelteDeJong

http://www.hjalte.nl/tutorials/80-creating-an-addin-inventor-2025-and-later

http://www.hjalte.nl/tutorials/60-creating-an-inventor-addin

 

They contain everything you need, including the ability to use iLogic in Addin.

Message 3 of 14

PolemEngineering
Advocate
Advocate

I did, but I can't seem to get the right stuff together to make it work.

 

It is with the ISharedVariable interface. In the Object Browser is mentioned that, in a rule, this interface is implemented by the predefined object named SharedVariable. That's also how I use it in regular iLogic-rules. In Jelte's blog is mentioned that the AbstractRule-class currently contains 2 properties.

So I tried to add "Public Property SharedVariable As ISharedVariable" and in another attempt "Public SharedVariable As ISharedVariable" 

 

But I keep getting te error "Object reference not set to an instance of an object." when running something simple as this:

Try
    SharedVariable.Value("TestVariable") = "TestValue"
Catch ex As Exception
    MessageBox.Show(ex.Message, "Attempt to create SharedVariable 'TestVariable' with value 'TestValue'")
End Try

Could makes sense, because I don't do anything with the previously declared and assigned iLogicAutomation object.

 

As an alternative I now try to just notice the events and then trigger an external rule. I don't know yet if this will work. iLogic is only available from the Inventor interface when/after opening a document. For that reason I also check if the Automation is activated. Otherwise .activate()

 

Things remain confusing and I'm afraid I'm on the wrong track.

Btw, I run Inventor 2023.5.1

René van der Starre

0 Likes
Message 4 of 14

WCrihfield
Mentor
Mentor

Hi guys.  I am admittedly not experienced in add-in creation/development, but I may still be able to help here.  The iLogic 'Rule Object' named "SharedVariable" is one of those thing that is automatically created for us in the background, within the other half of the 'Public Partial Class ThisRule' that we generally never see.  And it uses a method for setting its value that does not seem to be available to us on 'our side' of that Class (in our regular iLogic rules).  The only way I know how to set the value of a variable of that ISharedVariable type is by using one of the two following uniquely iLogic paths to get an IStandardObjectProvider:

Oddly enough the 'StandardObjectFactory' seems to already exist, and is ready for us to use in our iLogic rules, and in external rules marked as Straight VB Code'.

However, standard practice is to 'pass' the 'iLogicVb or InventorVb' (ILowLevelSupport Interface) object to our external resource, one way or another, then use that to set the value of a local variable, then go from there.  But I'm not sure how that would work in an add-in.

Once you have that IStandardObjectProvider, you can create most of those other 'rule objects', and they will be 'scoped or focused on' to that Document you specified.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 14

PolemEngineering
Advocate
Advocate

If I understand correctly, you need a document as an input at all times? In that case, this function may seem less useful. I want an event handler that remains active during the entire Inventor session.
A SharedVariable does remain active during the session. Is SharedVariable actually something completely different in the background? A List or something?

 

I took SharedVariable, because it is something I know and is very useful to warn the user once per session or something. Maybe I should take something else as temporary Object.

René van der Starre

0 Likes
Message 6 of 14

WCrihfield
Mentor
Mentor

Actually, the question about how SharedVariables came up in a pretty recent forum discussion, and Mike Deck (Autodesk developer & Inventor API expert) mentioned that they are essentially backed by a Dictionary(Of String, Object).  The question at that moment was..."Where can I find a list of all currently existing SharedVariables?"  He said that is not available at the moment, but that it could fairly easily be implemented.  He also suggested that we create our own new SharedVariable with a 'New Document(Of String, Object)' as its value.  Then any time during that session, store everything in that existing shared dictionary.  That way we have a good way to find what exists.  Not perfectly fool proof, but a great idea.

Also, even though that method mentioned above takes a Document as input, I can not be sure that if you create a SharedVariable using that resulting IStandardObjectProvider (IStandardObjectProvider.SharedVariable Property) that it will somehow be linked to that Document.  Some of those things may simply not be able to have an association that way, not sure.  I didn't design all that iLogic stuff, just a regular 'user' who's been 'snooping' quite a bit for quite a while.

 

Edit:  Found that discussion thread...link below:

https://forums.autodesk.com/t5/inventor-programming-ilogic/list-of-current-sharedvariables/m-p/13137... 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 14

JelteDeJong
Mentor
Mentor

Maybe you can take another route and create your own class with your variable. And then get the object containing your variable in the ilogic rule from your addin. It works something like this. Your StandardAddInServer would look something like this:

<GuidAttribute("[YOUR GUID]"), ComVisible(True)>
Public Class StandardAddInServer
    Implements Inventor.ApplicationAddInServer

    Private _myVariableObject As MyVariableObject

    Public Sub Activate(AddInSiteObject As ApplicationAddInSite, FirstTime As Boolean) Implements ApplicationAddInServer.Activate
        _myVariableObject = New MyVariableObject()
        _myVariableObject.MyVariable = "TEST"
    End Sub

    Public ReadOnly Property Automation As Object Implements ApplicationAddInServer.Automation
        Get
            Return _myVariableObject
        End Get
    End Property
End Class

Public Class MyVariableObject
    Public Property MyVariable As String
End Class

Notice:

  • Notice the GUID on line 1. You need it in the iLogic rule.
  • on line 19, 20 en 21: we have a class that we can use in the ilogic rule
  • on line 5,  8 en 9: we initialize the variable and  set some value
  • on line 12 to 16: You find something that is not in the tutorial. but here the magic happens. This function can be called from within the iLogic rule. And it returns our object.

Now in your iLogic rule you can do this:

Dim addIn As ApplicationAddIn = ThisApplication.ApplicationAddIns.ItemById("{[YOUR GUID]}")
Dim myVariableObject = addIn.Automation

msgbox(myVariableObject.MyVariable)

On line 1 and 2 you get the object from your addin.

Then you can use it. For example in a MsgBox like on line 4 😁. It this case that would look like this:

JelteDeJong_0-1732312927906.png

 

 

 

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.

EESignature


Blog: hjalte.nl - github.com

Message 8 of 14

PolemEngineering
Advocate
Advocate

Wow! It's great that this forum, with its active users, exists. Thanks for all the responses @m_baczewski , @WCrihfield  and @JelteDeJong!

This gives me a lot to think about. I also gained some more insight into the possible interaction between different class libraries. I have already made several simple AddIn's and StandAlone applications, but always very basic. This info adds a lot to my pallet of possibilities. I'll get to work on it.

Thanks again.

René van der Starre

0 Likes
Message 9 of 14

PolemEngineering
Advocate
Advocate

Hmm, strange.

I followed your explanation to the letter. Running the iLogic-rule results in a System.NullReferenceException: 'Object variable or With block variable not set.' when getting the .MyVariable (at line 4 in your example)...

 

In de 'Active'-sub routine I then added a Try-block with 3 messageboxes to follow the progress.

MessageBox.Show("Started")
Try
    ' initialize the MyVariableObject class
    _myVariableObject = New MyVariableObject()
    _myVariableObject.MyVariable = "Test"
Catch ex As Exception
    ' Show a message if any thing goes wrong.
    MessageBox.Show(ex.Message)
End Try
MessageBox.Show("Succeeded?")

No exception thrown. The other two messages are shown.

 

I can get the name of the AddIn. It is also activated (of course, because it shows two Message Boxes)

If I set the last line of the iLogic-rule example in an if-block it goes for the 'else'...

Dim addIn As ApplicationAddIn = ThisApplication.ApplicationAddIns.ItemById("{bec4b251-a925-4ac7-828b-0bd050b2b6de}")
Logger.Info(addIn.DisplayName)
Dim myVariableObject As Object = addIn.Automation

If Not (myVariableObject Is Nothing) Then
	Logger.Info(myVariableObject.MyVariable)
Else
	Logger.Info("Apparently the object remains Nothing")
End If

 

What could go wrong in this very simple code?

 

Using Autodesk Inventor 2023.5.1. Microsoft Visual Studio 2022. Class Library with .NET Framework 4.8.1

René van der Starre

0 Likes
Message 10 of 14

PolemEngineering
Advocate
Advocate

Wrong post

René van der Starre

0 Likes
Message 11 of 14

JelteDeJong
Mentor
Mentor

Just as a test you could change the function StandardAddInServer.Automation(...) in your addin to something like this:

 

    Public ReadOnly Property Automation As Object Implements ApplicationAddInServer.Automation
        Get

		If Not (_myVariableObjectIs Nothing) Then
			MsgBox(_myVariableObject.MyVariable)
		Else
			MsgBox("Apparently the object remains Nothing")
		End If


        	Return _myVariableObject
        End Get
    End Property

Now run your iLogic code. You should get a messagebox from your addin. 

If your variable _myVariableObject is here also nothing then I expect that there is something wrong in the function StandardAddInServer.Activate(...) In my previous example I set the values on lines 8 and 9

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.

EESignature


Blog: hjalte.nl - github.com

Message 12 of 14

PolemEngineering
Advocate
Advocate

With this modification the _myVariableObject is apparently Not Nothing... I got a messagebox showing the MyVariable-value.

Does this mean that the problem must be found on the iLogic or Inventor side?

 

StandardAddInServer.vb:

Option Strict On
Option Explicit On
Imports System.Runtime.InteropServices
Imports Inventor
Imports System.Windows.Forms

<GuidAttribute("bec4b251-a925-4ac7-828b-0bd050b2b6de"), ComVisible(True)>

Public Class StandardAddInServer
    Implements Inventor.ApplicationAddInServer

	Public Sub Activate(AddInSiteObject As ApplicationAddInSite, FirstTime As Boolean) Implements ApplicationAddInServer.Activate
		MessageBox.Show("Started")
		_myVariableObject = New MyVariableObject With {
			.MyVariable = "Test"
		}
		MessageBox.Show("Succeeded?")
	End Sub
	
    Public ReadOnly Property Automation As Object Implements ApplicationAddInServer.Automation
        Get
            If Not (_myVariableObject Is Nothing) Then
                MsgBox(_myVariableObject.MyVariable)
            Else
                MsgBox("Apparently the object remains Nothing...")
            End If
            Return _myVariableObject
        End Get
    End Property

End Class

Public Class MyVariableObject
    Public Property MyVariable As String
End Class

 

 

René van der Starre

0 Likes
Message 13 of 14

Curtis_Waguespack
Consultant
Consultant
Accepted solution

@PolemEngineering 

Maybe you could:

  • create an external rule that sets the variables
  • and then  create a module in Visual Studio to call the rule
  • and then add a line in the StandardAddinServer to call the module in Visual Studio that runs the rule

 

This line is in your StandardAddInServer:

 

 

Run_External_iLogic_Rule.RunExternalRule("My External Rule To Set Shared Variables")

 

 

 

This would be the module in Visual Studio that calls external rules by name:

 


Imports Inventor

Module Run_External_iLogic_Rule


    Public Sub RunExternalRule(ByVal ExternalRuleName As String)

        Try

            ' The application object.
            Dim addIns As ApplicationAddIns = g_inventorApplication.ApplicationAddIns()

            ' Unique ID code for iLogic Addin
            Dim iLogicAddIn As ApplicationAddIn = addIns.ItemById("{3BDD8D79-2179-4B11-8A5A-257B1C0263AC}")

            ' Starts the process
            iLogicAddIn.Activate()

            ' Executes the rule
            iLogicAddIn.Automation.RunExternalRule(g_inventorApplication.ActiveDocument, ExternalRuleName)

        Catch ex As Exception

            MsgBox("Error launching external rule: " & vbLf & "     " & ExternalRuleName _
                   & vbLf & vbLf & "Ensure the iLogic rule exists, and that the" _
                   & vbLf & "configuration includes the path to the rules." _
                   & vbLf & vbLf & "see Tools tab > Options flyout button > iLogic Configuration button" _
                   & vbLf & "    If needed, add an external rules folder path," _
                   & vbLf & "    and ensure that the rule is found in this folder.")
            Return

        End Try

    End Sub

End Module

 

 

 

Something like this would be the external rule:

SharedVariable("Test Variable 01") = "hello"
SharedVariable("Test Variable 02") = "world"

 

EESignature

Message 14 of 14

PolemEngineering
Advocate
Advocate

Thanks @Curtis_Waguespack for this route.

In the beginning I had a bit of trouble with an error (Object reference not set to an instance of an object). It took me a while to realize that the document (which every iLogic command apparently has to refer to) had not yet been loaded when "Public Sub Activate" was activated.

I have now defined some events in which the Rules are called. The "Public Sub Activate" now only initiates the necessary things. In fact, I now have an EventHandler-AddIn. Some Events already take place without an active document. The need for executing a Rule is then already known and is then placed in a kind of queue by means of a condition. This saves a lot of unnecessary rule activity.

Thanks again for everyone's input! I have learned a lot again.

Too bad I wasn't able to find out why @JelteDeJong suggestion didn't work because that seemed like a good solution just as well.

 

René van der Starre

0 Likes