Toggling JITExtension in C#

799
9
04-07-2010 03:43 PM
RobChasan
New Contributor III
ArcObjects /C#.NET/ArcMap 9.3.1 SP1

I have created a JITExtension that must NOT appear in the Extension Manager.  How can it be toggled on and off from code?
0 Kudos
9 Replies
KirkKuykendall
Occasional Contributor III
If you don't implement IExtensionConfig, then I don't think it will show up in the Extension Manager window.

Any tools/commands etc. that need to see if the extension is toggled on, should first check to see if it is loaded using IJITExtensionManager.IsLoaded, if it is not loaded I guess that means it isn't "on" - otherwise access access an Enabled method.  This could be done as a static method on your extension.
0 Kudos
RobChasan
New Contributor III
Thanks for the quick reply Kirk.

As we don't want to give the users access to this extension via the Configuration Manager, implementing IExtensionConfig is out.

Not sure if I completely get what you are saying about accessing an Enabled method.  IExtension does not have one.  Are you suggesting that the JITExtension do something like inherit from ICommand in addition to IExtension and then use the ICommand's Enabled property?  Or am I complicating this?
0 Kudos
KirkKuykendall
Occasional Contributor III
Just implement IExtension like you normally would, but instead of implementing IExtensionConfig - which would make it show up in the Extensions window - write a static method called Enabled.  It would follow the singleton pattern, with a static member variable reference to to m_MyExtension.  If the m_MyExtension == null, Enabled would return false, otherwise it would use another boolean member variable m_Enabled.

You'll need to write a command to toggle it for you, since it won't appear in the Extensions window.
0 Kudos
RobChasan
New Contributor III
Could I trouble you to provide a snippet of how the Enabled method should be coded?  (I still have trouble converting OOP-speak into code).
0 Kudos
KirkKuykendall
Occasional Contributor III
Here's a command that toggles the extension:
#region Overriden Class Methods

/// <summary>
/// Occurs when this command is created
/// </summary>
/// <param name="hook">Instance of the application</param>
public override void OnCreate(object hook)
{
    m_application = hook as IApplication;
}

/// <summary>
/// Occurs when this command is clicked
/// </summary>
public override void OnClick()
{
    JITExtension1.SetEnabled(m_application, !JITExtension1.GetEnabled());
}
public override bool Checked
{
    get
    {
        return JITExtension1.GetEnabled();
    }
}
#endregion


Here's the extension:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.ADF.CATIDs;

namespace Forums
{
    [Guid("7c6aee7a-5e63-497d-a897-551ab8f6f761")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("Forums.JITExtension1")]
    public class JITExtension1 : IExtension
    {
        #region COM Registration Function(s)
        [ComRegisterFunction()]
        [ComVisible(false)]
        static void RegisterFunction(Type registerType)
        {
            // Required for ArcGIS Component Category Registrar support
            ArcGISCategoryRegistration(registerType);

            //
            // TODO: Add any COM registration code here
            //
        }

        [ComUnregisterFunction()]
        [ComVisible(false)]
        static void UnregisterFunction(Type registerType)
        {
            // Required for ArcGIS Component Category Registrar support
            ArcGISCategoryUnregistration(registerType);

            //
            // TODO: Add any COM unregistration code here
            //
        }

        #region ArcGIS Component Category Registrar generated code
        /// <summary>
        /// Required method for ArcGIS Component Category registration -
        /// Do not modify the contents of this method with the code editor.
        /// </summary>
        private static void ArcGISCategoryRegistration(Type registerType)
        {
            string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
            MxExtensionJIT.Register(regKey);

        }
        /// <summary>
        /// Required method for ArcGIS Component Category unregistration -
        /// Do not modify the contents of this method with the code editor.
        /// </summary>
        private static void ArcGISCategoryUnregistration(Type registerType)
        {
            string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
            MxExtensionJIT.Unregister(regKey);

        }

        #endregion
        #endregion
        private IApplication m_application;
        private bool m_Enabled;

        private static JITExtension1 m_instance;
        public bool Enabled
        {
            get { return m_Enabled; }
            set { m_Enabled = value; }
        }
        public static bool GetEnabled()
        {
            if(m_instance == null)
                return false;
            else
                return m_instance.Enabled;
        }
        public static void SetEnabled(IApplication app, bool enabled)
        {
            if (m_instance == null)
            {
                UID uid = new UIDClass();
                uid.Value = "{7c6aee7a-5e63-497d-a897-551ab8f6f761}";
                // this will cause instantiation (and Startup will get called)
                JITExtension1 ext =  app.FindExtensionByCLSID(uid) as JITExtension1;
                ext.Enabled = enabled;
            }
            else
                m_instance.Enabled = enabled;
        }

        #region IExtension Members

        /// <summary>
        /// Name of extension. Do not exceed 31 characters
        /// </summary>
        public string Name
        {
            get
            {
                //TODO: Modify string to uniquely identify extension
                return "JITExtension1";
            }
        }

        public void Shutdown()
        {
            //TODO: Clean up resources

            m_application = null;
            m_instance = null;
        }

        public void Startup(ref object initializationData)
        {
            m_instance = this;
            m_application = initializationData as IApplication;
        }

        #endregion
    }
}
0 Kudos
RobChasan
New Contributor III
Kirk, you make it look so easy!  I probably would not have figured this out on my own, certainly not in any reasonable amount of time.  Thanks again.
0 Kudos
GailNagle
New Contributor
Hello,
I am replying to this thread since it is the only hit I got on a forum search of IJITExtensionManager. My question is much more fundamental. First, I am coding in C++ but conceptually this should have no bearing on the answer. The question is related to what "loading" means for an ArcMap extention. As far as I can tell, even though our extention implementation contains the code below, the DLL is still being loaded when ArcMap starts up.
BEGIN_CATEGORY_MAP(CSfaExt)
IMPLEMENTED_CATEGORY(__uuidof(CATID_MxExtensionJIT))
END_CATEGORY_MAP()
If it is being loaded, meaning that LoadLibrary() or LoadLibraryEx() has been called on our DLL, then this is not truly Just-In-Time loading. If we need to change the WINDOWS registration of a library once ArcMap has started, how can we truly control the loading of the DLL? Do we need to skip registration entirely and call LoadLibrary() ourselves in a seed DLL that is registered? Would this approach work with ArcMap? Having spent a week trying different approaches, and getting nowhere fast, your help would be greatly appreciated!

Thanks,
Gail
0 Kudos
KirkKuykendall
Occasional Contributor III
I think "loaded" means IExtension.Startup has been called.  Of course the dll containing the extension will be loaded into memory before that.  If you have a DLL that is expensive to load (e.g. big) then maybe you could have a small light-weight DLL containing the class that implements IExtension, and have it load the large DLL when Startup is called.
0 Kudos
GailNagle
New Contributor
Hello Kirk,

Thanks for the reply. This is exactly what I hoped to do but was not sure how to exactly "load" the larger DLL. Of course I can call LoadLibrary(). In this scenario, I would not call regsvr32 to register the DLL since then it will be automatically loaded by ESRI. But I assume there must be some code that must run to allow ArcMap to handle its bookkeeping on a DLL. So I am not sure how this would work. But if you can shed any more light, I would be most grateful!

Thanks again,
Gail Nagle
0 Kudos