Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Development Advice and Strategy

Brett.G
Enthusiast

Development Advice and Strategy

Brett.G
Enthusiast
Enthusiast

Hello!  I'm hoping to get some suggestions from some of the more experienced developers out there.  I have been able to create some useful tools that I've bundled into an add-in for inventor. I have three tools that are each a button on a toolbar in a ribbon and perform separate tasks.  I do my development in Visual Studio Community and have one Solution with all the tools in them.  When I build the solution it generates one dll file and the other necessary files for the add in.   

 

What I'm wondering is if this is the way it is typically done?  I'm curious if it is possible or recommended to have separate dlls for each tool, however, I'm not sure how to accomplish this, and I'm finding it difficult to search for resources.  The reason I'm thinking of separate dll/tool is to better control versioning of those tools.   Any suggestions would be appreciated! 

0 Likes
Reply
1,123 Views
9 Replies
Replies (9)

AlexFielder
Advisor
Advisor

Hi @Brett.G,

 

When I originally started developing tools for Inventor (nearly a decade ago, time flies!) I had them all bundled in one solution like you.

 

Recently, since I've created add-ins for different customers, I've resorted to having different projects (within the same Solution) that build to the same location. As you point out, this makes it easier to manage version changes between functions and allows me to release a particular plugin to a specific customer.

 

The one BIG downside is that it required a method to load the individual "function .dlls" into Inventor all at once. To accomplish this I use the Managed Extensibitily Framework (MEF) which allows me to take care of the loading into Inventor itself with one ExtensionServer/.addin file and each "function" has it's own .dll with it's own resources and (optional) settings file.

 

What I haven't figured out as yet is whether it's possible to unload a .dll loaded in this way. My brief research (admittedly three years ago) says that it's not possible, but am happy to hear if this is no longer the case.

 

:slightly_smiling_face:

GeorgK
Advisor
Advisor

Hello @AlexFielder ,

 

please could you share an code example how you get it working.

 

Thank you very much

Georg

0 Likes

AlexFielder
Advisor
Advisor

Hi @GeorgK,

 

I figured someone would ask that, I'll see what I can rustle up.

 

:slightly_smiling_face:

Brett.G
Enthusiast
Enthusiast

Thanks for the reply Alex.  I'll have to read up on MEF, I've never heard about it nor do I really understand it.    I did think of another question after reading your comment.  If I have all my tools in the same Solution, and those get built as separate dlls with all their files (config, .addin, etc)  the user would have to enable each addin through the addin manager correct?  Do you use the MEF to avoid this?   

 

So the benefit of using MEF is that you have one addin that you enable through the addin manager but each tool can have its own resources like you said.  Is this correct?  In my case I don't think it is out of the question to enable each tool in the addin manager.  Would you still recommend using MEF in this case?  Thank you!

0 Likes

AlexFielder
Advisor
Advisor

Hi @Brett.G,

 

Simply put, yes.

 

If you want to have a shared library of wrappers such as methods for working with iProperties/Parameters, you could quickly end up with a bunch of duplicate library files as Visual Studio would (by default) create copies of these libraries local to each compiled "function" dll and its accompanying .addin file.

 

This is my main reason for using MEF (which is properly explained here with an example, downloadable solution in case you missed the earlier link):

 

https://docs.microsoft.com/en-us/dotnet/framework/mef/

 

Since it allows me to have one central project with the following file(s):

  • A single .addin file
  • A single extension server .dll file
  • A single "Contracts" .dll file (more on this in a bit)
  • A single Don't Repeat Yourself (DRY) Helpers .dll file (takes care of Parameter/iProperty-specific wrappers)
  • An append-able settings methodology (allows for user-controllable renaming of key properties)

As part of the single extension server file it affords the ability to add any of the following:

  • a Ribbon button (or collection thereof)
  • a context-menu button (right-click)
  • a dockable window
  • a graphics UI-specific "function"

The requirements for the items above are governed by the use of the "Contracts" .dll file mentioned earlier. Wherein the contract for each defines exactly what the Inventor Function extension should contain in order to load correctly.

 

I'm currently working out the technical details in a new github-hosted extension to show how all this works.

 

FWIW here's the basic "contract" Interface I'm using:

Interface IVPlugin
    Private Property LogFileHelper As GraitecLog4NetFileHelper
    Private ReadOnly Property CommandName As String
    Private ReadOnly Property Description As String
    Private ReadOnly Property DefaultResourceName As String
    Private ReadOnly Property EnvironmentRibbonName As EnvironmentRibbonName
    Private Property InventorApp As Application
    Sub Execute()
    Private ReadOnly Property InsertBeforeTarget As Boolean
    Private ReadOnly Property Path As String
    Private ReadOnly Property TargetControlName As String
    Private ReadOnly Property ToolTip As String
    Private ReadOnly Property PluginSettingsPrefix As String
    Private Property PluginSettingsPrefixVar As String
    Private Property ParentSettingsFilePath As String
End Interface

And here's the basic IVButtonPlugin interface that builds on the requirements of the above:

Interface IVButtonPlugin
    Inherits IVPlugin

    Private ReadOnly Property DisplayBigIcon As Boolean
    Private ReadOnly Property DisplayText As Boolean
    Private ReadOnly Property ButtonInternalName As String
    Private ReadOnly Property ButtonDisplayName As String
    Private ReadOnly Property RibbonPanelName As String
    Private ReadOnly Property CanHaveProgressiveToolTip As Boolean?
    Private ReadOnly Property IncludesProgressiveToolTipHelp As Boolean
    Private Property ProgressiveToolTipDescription As String
    Private Property ProgressiveToolTipExpandedDescription As String
    Private Property ProgressiveToolTipTitle As String
    Private Property ProgressiveToolTipImagePath As String
    Private Property ThisButtonDefinition As ButtonDefinition
    Sub ButtonDefinition_OnHelp(ByVal Context As NameValueMap, <Out> ByRef HandlingCode As HandlingCodeEnum)
End Interface

When I have something that is more than just words I'll share the link here.

Brett.G
Enthusiast
Enthusiast

Alex,  thanks again for the reply.  Looks like I have a lot to learn about now!

0 Likes

AlexFielder
Advisor
Advisor

Hi @Brett.G 

 

I finally got time to update the repo I started and you can see the branches here:

https://github.com/AlexFielder/InventorExtensionServer/branches

 

I added the basic button branch today, and will add more as time allows. By way of a basic road-map I plan the branches to progress as such:

 

Add-a-button-to-any-env.-ribbon > Add-a-button-to-any-env.-ribbon > Add-our-button-command-to-the-context-menu > Add-a-custom-ribbon-and-our-button-command-to-it > Add-useful-dockable-Window > Add-all-the-predecessors-to-separate-extension-projects

 

Colour Key to the above:

 

Complete-and-submitted

In-Progress-and-submitted

In-Progress locally

Thinking-out-loud

 

*Or something; I'm adding branches on the fly.

 

 

Brett.G
Enthusiast
Enthusiast

Thank you for the continued work Alex!

0 Likes

AlexFielder
Advisor
Advisor

Hi @Brett.G,

 

I'm just back from leave and tidied up the "context menu" code enough for a submit. So now the progress looks like this:

 

Add-a-button-to-any-env.-ribbon > Add-a-button-to-any-env.-ribbon > Add-our-button-command-to-the-context-menu > Add-a-custom-ribbon-and-our-button-command-to-it > Add-useful-dockable-Window > Add-all-the-predecessors-to-separate-extension-projects

 

Colour Key to the above:

 

Complete-and-submitted

In-Progress-and-submitted

In-Progress locally

Thinking-out-loud

 

*Or something; I'm adding branches on the fly.

0 Likes