One interesting little API gem is the ExtensionLoader. Well, it’s interesting to me because I designed it, but maybe you will find it interesting too. I basically took the mechanism for loading plug-ins and made it public in the API. In theory, you can make use of this tool to load extensions of your own. Another use is interrogating the system to see which Vault plug-ins are available, where they live, what their settings are, and so on.
In order to be loaded by the framework, a plug-in has to meet certain requirements.
- The plug-in has to work through an interface.
- The plug-in needs a class that implements the interface.
- The loader app needs to be aware of the interface.
- The implementing class needs a default constructor.
- There needs to be .vcet.config file, which is what tells the loader framework about the plug-in.
If you take a closer look at the .vcet.config for a 2014 plug in, you will notice that an <extension> contains an interface and type. Interface can be anything you want. IExplorerExtension, IJobHandler and IWebServiceExtension are the ones provided by the Vault API. But the loader framework doesn’t care about that. It will work with any .NET interface. Type is the class that implements the interface. The Loader creates a new instance of that class when loading the plug-in.
The loader framework can be access through the ExtensionLoader, which is in Autodesk.Connectivity.Extensibility.Framework. Here is a quick example I put together. It’s for an EXE that prints out the Vault Explorer extensions along with their custom commands and tabs.
ExtensionLoader loader = newExtensionLoader();
// load the plug-ins matching the IExplorerExtension interface
var extensions = loader.LoadExtensions<IExplorerExtension>();
foreach (Extension<IExplorerExtension> extension in extensions)
output.AppendLine("Extension " +
// create a new instance of the plug-in
// we are not going to run it
// we just want to read data from it
IExplorerExtension explorerExt = extension.NewInstance();
// ask the plug-in for it's commands
IEnumerable<CommandSite> customCommands =
if (customCommands != null && customCommands.Any())
output.AppendLine("- Custom commands: ");
foreach (CommandSite site in customCommands)
foreach (CommandItem command in site.CommandItems)
output.AppendLine("-- " + command.Label);
// ask the plug-in for it's custom tabs
IEnumerable<DetailPaneTab> customTabs =
if (customTabs != null && customTabs.Any())
output.AppendLine("- Custom tabs: ");
foreach (DetailPaneTab tab in customTabs)
output.AppendLine("-- " + tab.Label);
Dim loader AsNewExtensionLoader()
' load the plug-ins matching the IExplorerExtension interface
Dim extensions = loader.LoadExtensions(OfIExplorerExtension)()
ForEach extension AsExtension(OfIExplorerExtension) In extensions
output.AppendLine("Extension " + extension.ExtensionAssembly.ProductName)
' create a new instance of the plug-in
' we are not going to run it
' we just want to read data from it
Dim explorerExt AsIExplorerExtension = extension.NewInstance()
' ask the plug-in for it's commands
Dim customCommands AsIEnumerable(OfCommandSite) = _
If customCommands IsNotNothingAndAlso customCommands.Any() Then
output.AppendLine("- Custom commands: ")
ForEach site AsCommandSiteIn customCommands
ForEach command AsCommandItemIn site.CommandItems
output.AppendLine("-- " + command.Label)
' ask the plug-in for it's custom tabs
Dim customTabs AsIEnumerable(OfDetailPaneTab) = _
If customTabs IsNotNothingAndAlso customTabs.Any() Then
output.AppendLine("- Custom tabs: ")
ForEach tab AsDetailPaneTabIn customTabs
output.AppendLine("-- " + tab.Label)
Here is what the output looks like on my computer. As you can expect, I have a good number of plug-ins installed.
It’s not quite perfect. Duplicates show up because the command/tab shows up in different contexts. Also, DECO does have custom commands, but they are not shown here. The reason is that the plug-in was loaded outside the context of Vault Explorer, and DECO doesn’t like that.