Issue
How can you call an add-in command from a stand alone executable?
Solution
In order to make a remote connection possible between an external executable and our add-in, we need first to define an interface that will expose the callable method(s) of the AddIn : let’s name it DemoAddinInterface. This simple interface will be composed by only one method that takes a String as argument: void Execute(String params)
Then let’s make the AddIn class inherit from this interface and define its Execute method.
At last, we need to define the Automation Property of the AddIn that makes possible to call methods from a remote process.
using System;
using System.Runtime.InteropServices;
using Inventor;
using Microsoft.Win32;
using System.Windows.Forms;
namespace AutomationAddIn
{
//User Defined Interface Exposed through the Add-In Automation property
public interface AutomationInterface
{
void Execute(String param);
string GetParam();
}
[GuidAttribute("c2006d41-5b2e-49b9-b662-13ef2258b83c")]
public class StandardAddInServer :
Inventor.ApplicationAddInServer, AutomationInterface
{
// Inventor application object.
private Inventor.Application m_inventorApplication;
public StandardAddInServer()
{
}
#region ApplicationAddInServer Members
public void Activate(
Inventor.ApplicationAddInSite addInSiteObject,
bool firstTime)
{
// Initialize AddIn members.
m_inventorApplication =
addInSiteObject.Application;
}
public void Deactivate()
{
// Release objects.
Marshal.ReleaseComObject(m_inventorApplication);
m_inventorApplication = null;
GC.WaitForPendingFinalizers();
GC.Collect();
}
public void ExecuteCommand(int commandID)
{ }
// Set method for outside EXE
public void Execute(String param)
{
MessageBox.Show("------------ Execute Command with param: " + param + " ------------");
}
// Get method for outside EXE
public string GetParam()
{
string ret = "String Param from AutomationAddIn";
return ret;
}
public object Automation
{
// This property is provided to allow the add-in
// to expose an API of its own to other
// programs. Typically, this would be done by
// implementing the add-in's API interface in a
// class and returning
// that class object through this property.
get
{
return this;
}
}
#endregion
}
}
The implementation of the executable is quite straightforward: we just need to iterate through the Inventor add-ins collection to find our add-in(based on the classID here because it is unique, but can be something else, like the add-in internal name …).
Once we get the add-in, we just call its Automation property and get back an instance of the add-in interface, so we are now able to call the execute method.
Also in the project reference settings, we need to reference our add-in dll, to gain access to the “DemoAddin” namespace.
The code below contains two buttons: one calls the method Execute of the add-in. The other calls the method GetParam
using Inventor;
using AutomationAddIn;
namespace AutomationExe
{
public partial class Form1 : Form
{
private Inventor.Application mApplication;
private AutomationInterface mAddInInterface;
// get the add-in
public Form1()
{
InitializeComponent();
try
{
mApplication = System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application") as Inventor.Application;
}
catch
{
Type inventorAppType = System.Type.GetTypeFromProgID("Inventor.Application");
mApplication = System.Activator.CreateInstance(inventorAppType) as Inventor.Application;
}
mApplication.Visible = true;
//Iterates through Inventor Add-Ins collection
foreach (ApplicationAddIn oAddIn in mApplication.ApplicationAddIns)
{
//Looks for our DemoAddin CLSID;
if (oAddIn.ClassIdString == "{C2006D41-5B2E-49B9-B662-13EF2258B83C}")
{
//Calls Automation property
mAddInInterface = (AutomationInterface)oAddIn.Automation;
}
}
}
private void bSend_Click(object sender, EventArgs e)
{
mAddInInterface.Execute("This is string param from external Exe...");
}
private void bGet_Click(object sender, EventArgs e)
{
string param = mAddInInterface.GetParam();
MessageBox.Show("This is string param from AddIn: " + param);
}
}
}