How to find an extension


Summary
Extensions can act as a central point of customization for developers, especially when a number of custom commands and tools must share data or access common user interface (UI) components. An extension is the logical place to store this data and develop the UI components. The main reason for this is there is only one instance of an extension per running application, and given an IApplication interface, it is always possible to locate the extension and work with it.
This topic explains how to find and list extensions.


Finding extensions with IApplication

The most straightforward way to get a reference to an extension is to use either the FindExtensionByCLSID or FindExtensionByName method of IApplication. The following two code examples show how to get a reference to the ArcMap Editor extension.
To find the Editor extension by the unique identifier object (UID), see the following code:
[C#]
private void GetEditorExtension(IApplication application)
{
    //Find extension by CLSID or ProgId.
    UID extensionID = new UIDClass();
    extensionID.Value = "esriEditor.Editor"; 
        //{F8842F20-BB23-11D0-802B-0000F8037368}.
    IExtension editExtension = application.FindExtensionByCLSID(extensionID);
}
[VB.NET]
Sub GetEditorExtension (application As IApplication)
    'Find extension by CLSID or ProgId.
    Dim extensionID As New UIDClass()
    extensionID.Value = "esriEditor.Editor" '{F8842F20-BB23-11D0-802B-0000F8037368}.
    Dim editExtension As IExtension = application.FindExtensionByCLSID(extensionID)
End Sub
To find the Editor extension by the name string, see the following code:
[C#]
private void GetEditorExtensionByName(IApplication application)
{
    //Find extension by the name.
    IExtension editExtension = application.FindExtensionByName("ESRI Object Editor");
}
[VB.NET]
Sub GetEditorExtensionByName (application As IApplication)
    'Find extension by the name.
    Dim editExtension As IExtension = application.FindExtensionByName("ESRI Object Editor")
End Sub
For more information, see Names and IDs of Esri extensions under Working with ArcGIS Components, General reference, Names and IDs, Extensions.

Just-in-time extensions

Unlike FindExtensionByCLSID, FindExtensionByName only returns extensions that are already loaded in the application. Prior to ArcGIS 9.0, you could use both methods because all extensions were loaded at startup. When the just-in-time (JIT) extension type was introduced at 9.0 to improve application startup performance, these extensions were only loaded by request when FindExtensionByCLSID was called. On the other hand, FindExtensionByName does not perform extension loading for custom JIT extensions, so it may return nothing.
An extension is labeled as loaded only if its IExtension.Startup method has been called by the framework. An extension can be initialized but not loaded.
Many of the extension products shipped with ArcGIS for Desktop are implemented as JIT extensions. The application framework is still capable of loading some of these product extensions by name for backward capability, but it is highly recommended that you update your code using FindExtensionByCLSID instead.
FindExtensionByCLSID is guaranteed to return an extension if a valid identifier is provided. A number of Esri extension products can still be loaded by name; however, third-party JIT extensions must be loaded by the CLSID.

Listing extensions with extension manager interfaces

The application object also implements the IExtensionManager and IJITExtensionManager interfaces, which have properties to get a reference to a particular extension and to get a count of how many extensions are currently loaded. If you're using the IExtensionManager interface to iterate extensions, it will not list JIT extensions. Similarly, if you are using IJITExtensionManager, ordinary extensions are not listed. Iterating JIT extensions by calling FindExtensionByCLSID starts each JIT extension at that point, leaving them in this state until the application exits.
The following code shows how to list all extensions registered in the ArcGIS for Desktop application:
[C#]
private void ExtensionList(IApplication application)
{
    List < string > loadedExtensions = new List < string > ();
    List < string > unloadedExtensions = new List < string > ();

    //All extensions returned by extension manager have been loaded at startup.
    IExtensionManager regularExtManager = application as IExtensionManager;
    for (int i = 0; i < regularExtManager.ExtensionCount; i++)
    {
        IExtension ext = regularExtManager.get_Extension(i);
        loadedExtensions.Add(ext.Name);
    }

    //Use IsLoaded to test if a JIT extension has already been loaded by request.
    IJITExtensionManager jitExtManager = application as IJITExtensionManager;
    for (int i = 0; i < jitExtManager.JITExtensionCount; i++)
    {
        UID extID = jitExtManager.get_JITExtensionCLSID(i);
        if (jitExtManager.IsLoaded(extID))
        {
            IExtension ext = application.FindExtensionByCLSID(extID);
            loadedExtensions.Add(ext.Name);
        }
        else
        //Just show the extension ID.
        {
            unloadedExtensions.Add(extID.Value.ToString());
        }
    }

    //Print extension information.
    Console.WriteLine("Extensions loaded in Application:");
    foreach (string ext in loadedExtensions)
        Console.WriteLine("\t" + ext);
    Console.WriteLine("CLSID of extensions haven't been loaded yet:");
    foreach (string extID in unloadedExtensions)
        Console.WriteLine("\t" + extID);
}
[VB.NET]
Sub ExtensionList(ByVal application As IApplication)
    Dim loadedExtensions As New List(Of String)
    Dim unloadedExtensions As New List(Of String)
    
    'All extensions returned by extension manager have been loaded at startup.
    Dim regularExtManager As IExtensionManager = DirectCast(application, IExtensionManager)
    For i As Integer = 0 To regularExtManager.ExtensionCount - 1
        Dim ext As IExtension = regularExtManager.Extension(i)
        loadedExtensions.Add(ext.Name)
    Next
    
    'Use IsLoaded to test if a JIT extension has already been loaded by request.
    Dim jitExtManager As IJITExtensionManager = DirectCast(application, IJITExtensionManager)
    For i As Integer = 0 To jitExtManager.JITExtensionCount - 1
        Dim extID As UID = jitExtManager.JITExtensionCLSID(i)
        If jitExtManager.IsLoaded(extID) Then
            Dim ext As IExtension = application.FindExtensionByCLSID(extID)
            loadedExtensions.Add(ext.Name)
        Else 'Just show the extension ID.
            unloadedExtensions.Add(extID.Value.ToString())
        End If
    Next
    
    'Print extension information.
    Console.WriteLine("Extensions loaded in Application:")
    For Each ext As String In loadedExtensions
        Console.WriteLine("\t" + ext)
    Next
    Console.WriteLine("CLSID of extensions haven't been loaded yet:")
    For Each extID As String In unloadedExtensions
        Console.WriteLine("\t" + extID)
    Next
End Sub
IExtensionManager.FindExtension works similar to FindExtensionByCLSID or FindExtensionByName on IApplication. Although it accepts either a UID or a name string, the same rule applies when loading JIT extensions. Loading by UID is guaranteed to return an extension if a valid identifier is provided.

Getting enable state of configurable extensions

Some extensions are configurable with the Extension Manager dialog box that shows their enable state (esriExtensionState), product name, and description. These extensions implement IExtensionConfig, so you can access these properties programmatically with this interface. See the following code example:
[C#]
IExtensionManager extManager = application as IExtensionManager;
for (int i = 0; i < extManager.ExtensionCount; i++)
{
    IExtension ext = extManager.get_Extension(i);
    if (ext is IExtensionConfig)
    {
        IExtensionConfig extConfig = (IExtensionConfig)ext;
        if (extConfig.State == esriExtensionState.esriESEnabled)
            Console.WriteLine(extConfig.ProductName + " is enabled");
    }
}
[VB.NET]
Dim extManager As IExtensionManager = DirectCast(application, IExtensionManager)
For i As Integer = 0 To extManager.ExtensionCount - 1
    Dim ext As IExtension = extManager.get_Extension(i)
    If TypeOf ext Is IExtensionConfig Then
        Dim extConfig As IExtensionConfig = DirectCast(ext, IExtensionConfig)
        If extConfig.State = esriExtensionState.esriESEnabled Then
            Console.WriteLine(extConfig.ProductName + " is enabled")
        End If
    End If
Next

Enable state and JITextensions

A JIT extension can be enabled on the Extension Manager dialog box but still remain unloaded. If you use the IExtensionConfig approach to check the enable state, you will have to load the extension. The IJITExtensionManager interface provides the IsExtensionEnabled method to check the enable state without loading the extension. See the following code example:
[C#]
//Use IsExtensionEnabled for JIT extensions.
IJITExtensionManager jitExtManager = application as IJITExtensionManager;
for (int i = 0; i < jitExtManager.JITExtensionCount; i++)
{
    UID extID = jitExtManager.get_JITExtensionCLSID(i);
    if (jitExtManager.IsExtensionEnabled(extID))
    {
        Console.WriteLine("Extension with clsid {0} is enabled", extID.Value);
    }
}
[VB.NET]
'Use IsExtensionEnabled for JIT extensions.
Dim jitExtManager As IJITExtensionManager = DirectCast(application, IJITExtensionManager)
For i As Integer = 0 To jitExtManager.JITExtensionCount - 1
    Dim extID As UID = jitExtManager.get_JITExtensionCLSID(i)
    If jitExtManager.IsExtensionEnabled(extID) Then
        Console.WriteLine("Extension with clsid {0} is enabled", extID.Value)
    End If
Next
When IsExtensionEnabled returns false, the extension state can be either disabled or unavailable.

Putting it together

Often times, developers create a custom extension to act as a central point of customization, especially when a number of the custom commands and tools must share data or access common UI components. If you're taking advantage of the delay loading mechanism with JIT extensions, your custom commands, tools, and so on, are responsible for controlling when the extension is loaded by calling IApplication.FindExtensionByCLSID.
The following table contains tips on JIT extension loading for custom commands and tools, followed by the sample code:
Commands and tools
Description
ICommand.OnCreate
Delay extension loading (call IApplication.FindExtensionByCLSID) if possible. For example, load at ICommand.OnClick when the command is clicked. 
ICommand.Enabled
To synchronize this with the target  extension enable state, use IJITExtensionManager.IsExtensionEnabled instead of loading the extension.
Caption, category, bitmap, tooltip, message, and other command appearance properties
In general, it is not necessary to load and access the extension unless extension persisted data is required.
ICommand.OnClick, ITool.OnMouseDown, IMultiItem.OnPopup, etc. 
Get the extension by calling IApplication.FindExtensionByCLSID if it is the first time the extension is accessed in the component.
See the following code example of an extension and its command:
[C#]
namespace HowToFindExtension
{
    [Guid("64c932e1-23c4-4fbd-a46c-6274c766624b")][ClassInterface
        (ClassInterfaceType.None)][ProgId("HowToFindExtension.MyExtensionCommand")]
    public sealed class MyExtensionCommand: BaseCommand
    {
        private IApplication m_application;
        private UID m_targetExtID;
        public MyExtensionCommand()
        {
            base.m_category = ".NET Samples";
            base.m_caption = "Sample Extension Command";
            base.m_toolTip = "An extension command";
            base.m_name = "CSNetSamples_ExtensionCommand";
        }
        public override bool Enabled
        {
            get
            {
                IJITExtensionManager jitExtMgr = m_application as
                    IJITExtensionManager;
                return jitExtMgr.IsExtensionEnabled(m_targetExtID);
            }
        }
        public override void OnCreate(object hook)
        {
            m_application = hook as IApplication;
            m_targetExtID = new UIDClass();
            m_targetExtID.Value = "MyProject.JITConfigurableExtension";
        }
        public override void OnClick()
        {
            IExtension ext = m_application.FindExtensionByCLSID(m_targetExtID);
            //Code to access the extension object to respond to this event.
        }
    }

    [Guid("0695c804-105f-405d-81d4-8f0a90c19802")][ClassInterface
        (ClassInterfaceType.None)][ProgId("MyProject.JITConfigurableExtension")]
    public class JITConfigurableExtension: IExtension, IExtensionConfig
    {
        private IApplication m_application;
        private esriExtensionState m_enableState;
        #region IExtension Members
        public string Name
        {
            get
            {
                return "MyJITExtension";
            }
        }
        public void Shutdown()
        {
            m_application = null;
        }
        public void Startup(ref object initializationData)
        {
            m_application = initializationData as IApplication;
        }
        #endregion 
        #region IExtensionConfig Members
        public string Description
        {
            get
            {
                return "My JIT Configurable Extension" + System.Environment.NewLine 
                    + "This JIT extension is configurable.";
            }
        }
        public string ProductName
        {
            get
            {
                return "My JIT Configurable Extension";
            }
        }
        public esriExtensionState State
        {
            get
            {
                return m_enableState;
            }
            set
            {
                m_enableState = value;
            }
        }
        #endregion 
    }

}
[VB.NET]
<ComClass(MyExtensionCommand.ClassId, MyExtensionCommand.InterfaceId, MyExtensionCommand.EventsId), _
          ProgId("HowToFindExtension.MyExtensionCommand")> _
          Public NotInheritable Class MyExtensionCommand
    Inherits BaseCommand
    
    #Region "COM GUIDs"
    Public Const ClassId As String = "919f7e7e-a3b5-4229-bc1d-93d21f20d87d"
    Public Const InterfaceId As String = "405ad9f5-64c3-492c-ac78-aac032c828ba"
    Public Const EventsId As String = "70b29988-51ba-4891-9492-99c0cf30abb7"
    #End Region
    
    Private m_application As IApplication
    Private m_targetExtID As New UIDClass()
    
    Public Sub New()
        MyBase.New()
        MyBase.m_category = ".NET Samples"
        MyBase.m_caption = "Sample Extension Command"
        MyBase.m_message = "An extension command"
        MyBase.m_name = "VBNetSamples_ExtensionCommand"
    End Sub
    
    Public Overrides ReadOnly Property Enabled() As Boolean
    Get
    Dim jitExtMgr As IJITExtensionManager = DirectCast(m_application, IJITExtensionManager)
    Return jitExtMgr.IsExtensionEnabled(m_targetExtID)
    End Get
End Property

Public Overrides Sub OnCreate(ByVal hook As Object)
If Not hook Is Nothing Then
    m_application = CType(hook, IApplication)
    m_targetExtID.Value = "MyProject.JITConfigurableExtension"
End If
End Sub

Public Overrides Sub OnClick()
Dim ext As IExtension = m_application.FindExtensionByCLSID(m_targetExtID)
'Code to access the extension object to respond to this event.
End Sub

End Class


<ComClass(JITConfigurableExtension.ClassId, JITConfigurableExtension.InterfaceId, JITConfigurableExtension.EventsId), _
          ProgId("MyProject.JITConfigurableExtension")> _
          Public Class JITConfigurableExtension
    Implements IExtension
    Implements IExtensionConfig
    
    #Region "COM GUIDs"
    Public Const ClassId As String = "ff97e400-d940-486f-b92b-608bbae22132"
    Public Const InterfaceId As String = "d26ea3da-00a4-44c4-a91e-9cb0385c2db5"
    Public Const EventsId As String = "b38c1df9-8ec9-43c4-9522-22a27728a190"
    #End Region
    
    Private m_application As IApplication
    Private m_enableState As esriExtensionState
    
    Public Sub New()
        MyBase.New()
    End Sub
    
    #Region "IExtension Members"
    Public ReadOnly Property Name() As String Implements IExtension.Name
    Get
    Return "MyJITExtension"
    End Get
End Property


Public Sub Shutdown() Implements IExtension.Shutdown
    m_application = Nothing
End Sub

Public Sub Startup(ByRef initializationData As Object) Implements IExtension.Startup
    m_application = CType(initializationData, IApplication)
    If m_application Is Nothing Then Return
End Sub

#End Region

#Region "IExtensionConfig Members"
Public ReadOnly Property Description() As String Implements IExtensionConfig.Description
Get
Return "My JIT Configurable Extension" + System.Environment.NewLine + _
    "This JIT extension is configurable."
End Get
End Property

Public ReadOnly Property ProductName() As String Implements IExtensionConfig.ProductName
Get
Return "My JIT Configurable Extension"
End Get
End Property


Public Property State() As esriExtensionState Implements IExtensionConfig.State
    Get
    Return m_enableState
    End Get
    Set(ByVal Value As esriExtensionState)
    m_enableState = Value
    End Set
End Property

#End Region
End Class






To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
Development licensing Deployment licensing
ArcGIS for Desktop Basic ArcGIS for Desktop Basic
ArcGIS for Desktop Standard ArcGIS for Desktop Standard
ArcGIS for Desktop Advanced ArcGIS for Desktop Advanced