Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm having issues add a custom GP tool to my toolbox programmatically using c#. The tool gets added to my toolbox OK but then when I try to open it it fails adding a red cross to the tool and specifiying a message "Invalid Tool" - "Unable to execute selected tool". Can anyone help? See code below:

Factory class

#region Imports

using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.esriSystem;
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

#endregion

namespace GPTools
{
    [Guid("1a590719-bf03-4de6-ad17-ef1f70e676bb")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("GPTools.gpToolboxFactory")]
    public class gpMonsToolboxFactory : ESRI.ArcGIS.Geoprocessing.IGPFunctionFactory
    {

        #region "IGPFunctionFactory Implementations"

        public string Alias
        {
            get
            {
                return "Imports";
            }
        }

        public ESRI.ArcGIS.esriSystem.UID CLSID
        {
            get
            {
                return default(ESRI.ArcGIS.esriSystem.UID);
            }
        }

        public ESRI.ArcGIS.Geoprocessing.IGPFunction GetFunction(string Name)
        {
            IGPFunction gpFunction = null;
            switch (Name)
            {
                case "gpImportFile":
                    gpFunction = new gpImportFile();
                    break;
            }
            return gpFunction;
        }

        public ESRI.ArcGIS.Geoprocessing.IEnumGPEnvironment GetFunctionEnvironments()
        {
            return null;
        }

        public ESRI.ArcGIS.Geodatabase.IGPName GetFunctionName(string Name)
        {
            IGPFunctionName gpFuncName = new GPFunctionNameClass();
            gpFuncName.MinimumProduct = esriProductCode.esriProductCodeViewer;
            IGPName gpName = gpFuncName as IGPName;

            switch (Name)
            {
                case "gpImportFile":
                    gpName.Category = "Data\\Import\\Raster";
                    gpName.Description = "Import File";
                    gpName.DisplayName = "Raster ZXY";
                    gpName.Name = "gpImportFile";
                    break;
            }
            gpName.Factory = this as IGPFunctionFactory;
            return gpName;
        }

        public ESRI.ArcGIS.Geodatabase.IEnumGPName GetFunctionNames()
        {
            IArray nameArr = new EnumGPNameClass();
            nameArr.Add(GetFunctionName("gpImportFile"));
            return (IEnumGPName)nameArr;
        }

        public string Name
        {
            get
            {
                return "Imports";
            }
        }

        #endregion

    }


}

IGPFunction:

using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.esriSystem;
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace GPTools
{
    [Guid("5f28c9a8-0998-4dc4-959c-5d32bb442910")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("GPTools.gpImportFile")]
    public class gpMonsImportZMapGrid : ESRI.ArcGIS.Geoprocessing.IGPFunction2
    {

        #region Variables

        private IGPUtilities2 _utils;

        #endregion

        #region Constructor

        public gpImportFile()
        {
            _utils = new GPUtilitiesClass();
        }

        #endregion

        #region "IGPFunction2 Implementations"
        public ESRI.ArcGIS.esriSystem.UID DialogCLSID
        {
            get
            {
                return null;
            }
        }

        public string DisplayName
        {
            get
            {
                return "Raster ZXY";
            }
        }

        public void Execute(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.esriSystem.ITrackCancel TrackCancel, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager envMgr, ESRI.ArcGIS.Geodatabase.IGPMessages message)
        {
            // Input File Path
            IGPParameter3 gpParam = (IGPParameter3)paramvalues.get_Element(0);
            string inputFile = gpParam.Value.GetAsText();

            // spatial reference
            gpParam = (IGPParameter3)paramvalues.get_Element(1);
            string spatRefPath = gpParam.Value.GetAsText();
            ESRI.ArcGIS.Geometry.ISpatialReference3 spatRef = Maersk.Functions.SpatialReference.LoadSpatRefFromPrj(spatRefPath);

            // output Grid
            gpParam = (IGPParameter3)paramvalues.get_Element(2);
            string outputGridFullPath = gpParam.Value.GetAsText();
            string outputDir = System.IO.Path.GetDirectoryName(outputGridFullPath);
            string outputGridName = System.IO.Path.GetFileName(outputGridFullPath);

            // Rest of process code...
        }

        public ESRI.ArcGIS.esriSystem.IName FullName
        {
            get
            {
                IGPFunctionFactory funcFact = new gpToolboxFactory();
                return (IName)funcFact.GetFunctionName(Name);
            }
        }

        public object GetRenderer(ESRI.ArcGIS.Geoprocessing.IGPParameter pParam)
        {
            //TODO: specify renderer
            return null;
        }

        public int HelpContext
        {
            get
            {
                return 0;
            }
        }

        public string HelpFile
        {
            get
            {
                return "";
            }
        }

        public bool IsLicensed()
        {
            // requires any version of ArcGIS
            return true;
        }

        public string MetadataFile
        {
            get
            {
                return "";
            }
        }

        public string Name
        {
            get
            {
                return "gpImportFile";
            }
        }

        public ESRI.ArcGIS.esriSystem.IArray ParameterInfo
        {
            get
            {

                IArray paramsArr = new ArrayClass();

                // input grid file
                IGPParameterEdit3 param = new GPParameterClass();
                param.Direction = esriGPParameterDirection.esriGPParameterDirectionInput;
                param.ParameterType = esriGPParameterType.esriGPParameterTypeRequired;
                param.DataType = new GPDataFileTypeClass();
                param.DisplayName = "Input file";
                param.Name = "inp_File";
                paramsArr.Add(param);

                // spatial reference
                param = new GPParameterClass();
                param.Direction = esriGPParameterDirection.esriGPParameterDirectionInput;
                param.ParameterType = esriGPParameterType.esriGPParameterTypeRequired;
                param.DisplayName = "Spatial Reference";
                param.DataType = new GPSpatialReferenceTypeClass();
                param.Name = "out_sr";
                paramsArr.Add(param);

                // etc...

                return paramsArr;
            }
        }

        string _inputFile = "";
        string _outputGrid = "";
        public void UpdateMessages(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager pEnvMgr, ESRI.ArcGIS.Geodatabase.IGPMessages Messages)
        {



        }

        public void UpdateParameters(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager pEnvMgr)
        {

        }
        #endregion



        public IGPMessages Validate(IArray paramvalues, bool updateValues, IGPEnvironmentManager envMgr)
        {
            return null;
        }
    }



}

Arctoolbox code:

   // Load toolbox into ArcToolbox
    IArcToolboxExtension arcTbxExt;
    try
    {
        arcTbxExt = (IArcToolboxExtension)ArcMap.Application.FindExtensionByName("ESRI ArcToolbox");
        if (arcTbxExt == null) { throw new Exception("ArcToolbox extension could not be found."); }
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show("Error finding ArcToolbox extension." + Environment.NewLine + " - " + ex.Message);
        return;
    }

    // open main toolbox
    IGPToolbox2 toolbox;
    try
    {
        if (System.IO.File.Exists(_settings.MainClass.MainToolBoxPath) == false) { throw new Exception("Toolbox does not exist." + Environment.NewLine + _settings.MainClass.MainToolBoxPath); }
        toolbox = Functions.Toolbox.OpenToolbox(_settings.MainClass.MainToolBoxPath);
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show("Error launching toolbox." + Environment.NewLine + " - " + ex.Message);
        return;
    }

    // Add toolbox
    try
    {
        arcTbxExt.ArcToolbox.AddToolbox((IGPToolbox)toolbox);
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show("Error adding toolbox." + Environment.NewLine + " - " + ex.Message);
        return;
    }

    #region Add .NET tools to tool

    //
    try
    {
        IGPFunctionFactory gpFuncFact = new GPTools.gpMonsToolboxFactory();
        IGPFunction gpFunction = gpFuncFact.GetFunction("gpImportFile");
        IGPTool gpTool = toolbox.CreateTool(esriGPToolType.esriGPFunctionTool, "gpImportFile", "Raster ZXY", "Imports a Raster file", "Import", null);
        IGPFunctionTool gpFuncTool = (IGPFunctionTool)gpTool;
        gpFuncTool.Function = gpFunction;
        gpTool.Store();
    }
    catch (Exception ex)
    {

        throw;
    }

EDIT: Thanks again too Petr Krebs who spotted the issue. For those who need it here's the answer in the factory class (alter the CLSID method):

public ESRI.ArcGIS.esriSystem.UID CLSID
{
    get
    {
        ESRI.ArcGIS.esriSystem.UID uid = new ESRI.ArcGIS.esriSystem.UID();
        // change uid here from the GUID specified at the class header
        uid.Value =  "{1a590719-bf03-4de6-ad17-ef1f70e676bb}";
        return uid;
    }
}
share|improve this question
    
Not sure if that's the cause of your problems, but your implementation of IGPFunctionFactory.CLSID is not correct - you're supposed to return the factory's GUID. –  Petr Krebs May 17 '11 at 12:26
    
THANKS!!!!!! That was it - I would have thought that the base class would have returned it as default. But that worked. If you stick it as an answer then I'll mark you as you've answered the question as I can't do that on comments. Thanks again! –  Rob Clark May 17 '11 at 12:58
    
There is no base class in your example, you are fully implementing the IGPFunctionFactory with no base implementation. Also, the "default" keyword does not call base implementations, it returns a default value for a type (e.g. null for reference types, 0 for numeric types etc.) –  Petr Krebs May 17 '11 at 14:33
    
yes I had a moment of confusion by something else that I was inheriting. –  Rob Clark May 18 '11 at 7:03
add comment

1 Answer 1

up vote 2 down vote accepted

Your implementation of IGPFunctionFactory.CLSID is not correct - it must return the function factory's GUID.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.