Select to view content in your preferred language

Locating AddIn Extension from a Button

2476
3
01-04-2010 06:02 AM
JochenManegold
Esri Contributor
How do I locate my AddIn Extension to use functionality within the code of an AddIn Button correctly. The "ArcMap.Application.FindExtensionByName(...)" is working, but I receive an IExtension Interface and its not possible to cast to other interfaces implemented into the AddIn Extension.
If I try this:
IExtension ext = ArcMap.Application.FindExtensionByName("myDemoExt");
IDemoExt demoExt = (IDemoExt)ext;
I receive the error:
"Unable to cast COM object of type 'System.__ComObject' to interface type 'Demo.IDemoExt'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{C1DA7464-AAA7-3B1E-8B02-BB571D92E278}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."
My AddIn Extension looks like this:
public class DemoExt : ESRI.ArcGIS.Desktop.AddIns.Extension, IDemoExt
0 Kudos
3 Replies
SteveVan_Esch
Esri Contributor
Communication between types within an add-in

Within most Add-In projects, some means for inter-component communication is needed so that one component can activate or obtain state from another; for example, a particular Add-In Button component�??when pressed�??may alter the overall Add-In state in a way which modifies the content displayed within an associated Add-In Dockview component. 
In the past, many developers have resorted to using COM based mechanisms for inter-component communication, defining custom interfaces which are then exposed from Button, Dockview or Extension components.  These interfaces are accessed by first finding the component using framework supplied find functions�??ICommandBar.Find, IApplication.FindExtension, etc.  The returned reference is then cast to the custom interface and used.  There are several downsides associated with this approach:


  • Using COM interfaces restricts communication to the simple types and calling patterns supported by COM and rules out the use of any language specific types and patterns. 


  • Communication between components within the same project is generally private; registering COM interfaces ostensibly publicizes these private communication lines and unnecessarily complicates any public interfaces intended for exposure outside the project.


  • COM interfaces need additional non-trivial coding steps and require registration within the system registry by an installer with administrative rights.  In .NET, such interfaces also require the generation and registration of Primary Interop Assemblies which introduce multiple native/managed context switches for each call (even though both ends of the conversation are managed).

Since, by design, Add-Ins cannot themselves rely on COM patterns and do not require registration, the traditional approach using COM isn�??t a viable option.  The alternative pattern is much more straightforward and has none of the associated downsides listed above.  Since all framework types are singletons, Add-In developers can use a simple approach based on static class members to achieve inter-component communication. 

The following example demonstrates how an extension can directly expose its functionality to other components within the same project:

public class MainExt : ESRI.ArcGIS.Desktop.AddIns.Extension
{
  private static MainExt s_extension;

  public MainExt()
  {
    s_extension = this;
  }

  internal static MainExt GetExtension()
  {
    // Extension loads just in time, call FindExtension to load it.
    if (s_extension == null)
    {
      UID extID = new UIDClass();
      extID.Value = "ACME_MainExt";
      ArcMap.Application.FindExtensionByCLSID(extID);
    }
    return s_extension;
  }

  internal void DoWork()
  {
    System.Windows.Forms.MessageBox.Show("Do work");
  }
}

Client code:

protected override void OnClick()
{
  MainExt mainExt = MainExt.GetExtension();
  mainExt.DoWork();
}
0 Kudos
DonParker
New Contributor
I know it's been awhile since this issue was posted, but I wanted to follow-up to determine if it is still possible to find an AddIn Extension the "old fashion" way (i.e. via the COM QueryInterface mechanism).  The reason I ask is because the "new" way forces me to add a direct reference to the AddIn Extension project/assembly that I want to use, whereas with the "old" way, I only had to add a reference to the project/assembly defining the "interface" that I wanted to use.  Several of your own examples show how to do it the "old" way (i.e. the PointsALongLineTool sample):

      //get the editor
      UID editorUid = new UID();
      editorUid.Value = "esriEditor.Editor";
      IEditor3 editor = m_application.FindExtensionByCLSID(editorUid) as IEditor3;


So of course, I would like to do something similar with my extension (such as "jm" reqested in the original post):

      IExtension ext = ArcMap.Application.FindExtensionByName("myDemoExt");
      IDemoExt demoExt = (IDemoExt)ext;

What do I need to do to my Extension class to make this possible?  I'm sure it probably involves using the COM interoperable stuff such as ComVisible, Guid, ClassInterface, ProgId, ComRegisterFunction, ComUnregisterFunction, etc.  Any help with this would be much appreciated.
0 Kudos
AndryJoos
Occasional Contributor
I currently having a similar problem: I need to access the extension residing inside my AddIn to be access from an outside, old-fashion COM component. I can get the AddIn extension by using FindExtensionByName, but then I can't cast it to my custom interface (implemented in the same class as the AddIn-Extension). Is that even possible, Esri? 🙂
0 Kudos