Building a custom geoprocessing function tool


SummaryThis topic is intended for developers who want to extend the geoprocessing (GP) framework by building new geoprocessing tools. This topic explains how to build a geoprocessing function tool and describes the ArcObjects components necessary to build this type of tool.

Development licensing Deployment licensing
ArcView ArcView
ArcEditor ArcEditor
ArcInfo ArcInfo
Engine Developer Kit Engine Runtime

In this topic


The sample tool referenced in this document is programmed with C# Microsoft Visual Studio 2005. Both C# and VB.NET code is provided in the associated sample, although this document just includes C# code snippets.

What is a geoprocessing tool?

A geoprocessing tool can be referred to as an operation that takes an input or set of inputs and generates one or more outputs. These inputs are referred to as parameters. Geoprocessing tools are located in toolboxes and categorized by functionality. Most geoprocessing tools provided by ESRI are implemented as Component Object Model (COM) function tools. A function tool requires implementing a minimum of two objects: a function object that implements IGPFunction and a function factory object that implements IGPFunctionFactory.
 
The following illustration shows the tool relationships, the classes implemented by ESRI, and the classes that are provided to extend the geoprocessing framework. There are four types of geoprocessing tools: GPModelTool, GPFunctionTool, GPCustomTool, and GPScriptTool.
 
 

Implementing IGPFunction

The IGPFunction interface is in the ESRI Geoprocessing library. IGPFunction provides access to the properties and methods required to build a function tool. The following lists each property and method with a brief description:

Tool parameters

When designing a geoprocessing function tool, the first step is to define the parameters and set their properties. An IGPParameter object is used to create and define the properties of a parameter. The ParameterInfo property returns an array of IGPParameter objects. The IGPParameter properties are as follows:
 
The following illustration shows some of the different data types and provides a code sample of creating a new FeatureClass parameter: 
 
 

ParameterType–Derived

What does it mean for a parameter to be derived? A derived parameter is used to indicate when the tool updates the input parameter. For example, the sample Building a custom geoprocessing function tool contains a derived parameter (CalculateArea). This tool adds a field to the input feature class and calculates the values for this new field. It requires no interaction from the user and does not show up on the UI or command line. It is used in ModelBuilder to indicate the changed state of the value and to provide proper chaining. Derived parameters are commonly dependent on an input table or feature class parameter.
 

Parameter DataType–Supporting layers and tables

To support layers and tables in ArcMap and ArcGlobe, the DataType for the parameter must be a FeatureLayer, RasterLayer, or TableView. For a complete list of layer DataType objects, see IGPLayerType.
 
The following code example defines the DataType of an input parameter to support feature layers:

[C#]
//Input DataType is GPFeatureLayerType.
IGPParameterEdit inputParameter = new GPParameterClass();
inputParameter.DataType = new GPFeatureLayerTypeClass();

[VB.NET]
' Input DataType is GPFeatureLayerType.
Dim inputParameter As IGPParameterEdit = New GPParameterClass 
inputParameter.DataType = New GPFeatureLayerTypeClass

Parameter DataType–Lists

In some cases, the parameter may be a table of one or more DataTypes. This data type is referred to as a ValueTable data type. An example of this is the Union tool. The input parameter for this tool is a table with two columns. The data type of the first column is a FeatureLayer, and the data type of the second column is a Long. The following code example defines a ValueTable DataType:
 

[C#]
// DataType is GPValueTableType.
IGPValueTableType valueTableType = new GPValueTableTypeClass();

// Value is GPValueTable.
IGPValueTable ValueTable = new GPValueTableClass();

// DataType for Column 1.
IGPDataType dataType1 = new GPFeatureLayerTypeClass();
valueTableType.AddDataType(dataType1, "input_Features", 100, Nothing);

// DataType for Column 2.
IGPDataType dataType2 = new GPLongTypeClass();
valueTableType.AddDataType(dataType2, "long", 100, Nothing);

// Add DataTypes to the GPValueTable.
valueTable.AddDataType(pDataType1);
valueTable.AddDataType(pDataType2);

// Set the Input Parameter.
IGPParameterEdit inputParameter = new GPParameterClass();
inputParameter.DataType = valueTableType;
inputParameter.Value = valueTable;

[VB.NET]
' DataType is GPValueTableType.
Dim valueTableType As IGPValueTableType = New GPValueTableTypeClass 

' Value is GPValueTable.
Dim ValueTable As IGPValueTable = New GPValueTableClass 

' DataType for Column 1.
Dim dataType1 As IGPDataType = New GPFeatureLayerTypeClass 
valueTableType.AddDataType(dataType1, "input_Features", 100, Nothing) 

' DataType for Column 2.
Dim dataType2 As IGPDataType = New GPLongTypeClass 
valueTableType.AddDataType(dataType2, "long", 100, Nothing) 

' Add DataTypes to the GPValueTable.
valueTable.AddDataType(pDataType1) 
valueTable.AddDataType(pDataType2) 

' Set the Input Parameter.
Dim inputParameter As IGPParameterEdit = New GPParameterClass 
inputParameter.DataType = valueTableType 
inputParameter.Value = valueTable

Parameter DataType–Composite

In other cases, the input value for the parameter may allow different DataTypes. This is referred to as a Composite DataType. This data type is used when the parameter can be more than one data type. An example of this is the Append tool. The input can be a raster, table, or feature class. The following code example defines a Composite DataType:
 

[C#]
// Create the GPCompositeDataType.
IGPCompositeDataType composisteType = new GPCompositeDataTypeClass();

// Create the DataTypes that are permitted as input.
IGPDataType dataType1 = new GPTableViewTypeClass();
IGPDataType dataType2 = new GPRasterLayerTypeClass();

// Add DataTypes.
compositeType.AddDataType(dataType1);
compositeType.AddDataType(dataType2);

// Set the Input Parameter.
IGPParameterEdit inputParameter = new GPParameterClass();
inputParameter.DataType = compositeType;
inputParameter.Value = new GPTableViewClass();

[VB.NET]
' Create the GPCompositeDataType.
Dim composisteType As IGPCompositeDataType = New GPCompositeDataTypeClass 

' Create the DataTypes that are permitted as input.
Dim dataType1 As IGPDataType = New GPTableViewTypeClass 
Dim dataType2 As IGPDataType = New GPRasterLayerTypeClass 

' Add DataTypes.
compositeType.AddDataType(dataType1) 
compositeType.AddDataType(dataType2) 

' Set the Input Parameter.
Dim inputParameter As IGPParameterEdit = New GPParameterClass 
inputParameter.DataType = compositeType 
inputParameter.Value = New GPTableViewClass

Validate() method

Validate() performs a lightweight verification that a given set of parameter values are of the appropriate number, DataType, and value. This method returns an IGPMessages object, identifying any warnings or errors, with a one-to-one correspondence to the array of parameter values. The IGPMessages object manages an array of IGPMessage objects. The GPEnvironmentManager is passed as input to Validate(). This provides access to all the current environments and settings of the current client.
 
The Validate() method has the following three important roles: 

[C#]
// Clone the input parameter value.
IGPParameter parameter = (IGPParameter)paramvalues.get_Element(0);
IGPValue parameterValue = m_GPUtilities.UnpackGPValue(parameter);
IClone parameterClone = (IClone)parameterValue;
IGPValue outputValue = (IGPValue)parameterClone.Clone();
IDETable inputTable = m_GPUtilities.DecodeDETable(outputValue);

// Add the Area field to the Output Value.
parameter = (IGPParameter)paramvalues.get_Element(1);
m_Field = parameter.Value.GetAsText();
if (inputTable != null)
{
IField areaField = m_GPUtilities.FindField(outputValue, m_Field);
       if (areaField == null)
       {
        IFieldsEdit fieldsEdit = (IFieldsEdit)inputTable.Fields;
               IFieldEdit fieldEdit = new FieldClass();
               fieldEdit.Name_2 = m_Field;
               fieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
               fieldsEdit.AddField(fieldEdit);
               inputTable.Fields = fieldsEdit;
        }

        parameter = (IGPParameter)paramvalues.get_Element(2);
        m_GPUtilities.PackGPValue(outputValue, parameter);
}

[VB.NET]
' Clone the input parameter value.
Dim parameter As IGPParameter = CType(paramvalues.Element(0), IGPParameter)
Dim parameterValue As IGPValue = m_GPUtilities.UnpackGPValue(parameter)
Dim parameterClone As IClone = CType(parameterValue, IClone)
Dim outputValue As IGPValue = CType(parameterClone.Clone, IGPValue)
Dim inputTable As IDETable = m_GPUtilities.DecodeDETable(outputValue)

' Add the Area field to the Output Value.
parameter = CType(paramvalues.Element(1), IGPParameter)
m_Field = parameter.Value.GetAsText

If Not (inputTable Is Nothing) Then
 Dim areaField As IField = m_GPUtilities.FindField(outputValue, m_Field)

 If areaField Is Nothing Then
   Dim fieldsEdit As IFieldsEdit = CType(inputTable.Fields, IFieldsEdit)
   Dim fieldEdit As IFieldEdit = New FieldClass
   fieldEdit.Name_2 = m_Field
   fieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble
   fieldsEdit.AddField(fieldEdit)
   inputTable.Fields = fieldsEdit
 End If

parameter = CType(paramvalues.get_Element(2), IGPParameter)
m_GPUtilities.PackGPValue(outputValue, parameter)

Execute() method

The arguments to the Execute() method include an array of parameter values, a GPMessages object, a TrackCancel object, and the GPEnvironmentManager. The GPMessages object is used for any returned messages to indicate if the function failed. The TrackCancel object is used to allow the functions the capability to cancel the operation and track its progress. The GPEnvironmentManager provides access to all the current environments and geoprocessing settings.
 
The Execute() method has the following four important roles:
 

[C#]
// Check if OverWrite setting is set.
IGeoProcessorSettings settings = (IGeoProcessorSettings)envMgr;
if (settings.OverwriteOutput)
if (m_GPUtilities.Exists(parameterValue))
        m_GPUtilities.Delete(parameterValue);
       else
        if (m_GPUtilities.Exists(parameterValue))
               {
                message.AddError(2, "Output already exists.");
                       return;
               }

[VB.NET]
' Check if OverWrite setting is set.
Dim settings As IGeoProcessorSettings = CType(envMgr, IGeoProcessorSettings)

If settings.OverwriteOutput Then
 
 If m_GPUtilities.Exists(parameterValue) Then
 
   m_GPUtilities.Delete(parameterValue)
 
 Else
 
   If m_GPUtilities.Exists(parameterValue) Then

     message.AddError(2, "Output already exists.")
     Return

   End If

 End If

End If
 

GPEnvironmentManager

The GPEnvironmentManager is the managing object for all the environments and settings used by the geoprocessing tools. The GPEnvironmentManager is passed to each tool for use during both Validate() and Execute(). The tool then has access to all the current environments and settings of the current application.

GPMessages

The GPMessages object manages an array of GPMessage objects. This object contains methods to generate and replace message objects. The Validate() method returns a GPMessages object that contains one message for each parameter. The Execute() method is passed an existing GPMessages object and simply adds new messages as needed.
 

GPMessage

The GPMessage object is composed of a message type, error code, and description. The type of message can be an error, a warning, or informative.
 

GPUtilities

The GPUtilities object contains many useful helper methods for the function writer. For a complete list of helper methods, see IGPUtilities. In the sample tool provided, many helper methods are used such as the following:
 

Implementing IGPFunctionFactory

Once the GPFunction tool is created, it must be made accessible. This is accomplished by creating a GPFunctionFactory. The factory is responsible for handing out the function name objects for each function. This factory is registered into the component category CATID_GPFunctionFactories.
 
A function factory is a logical grouping of tools. As a good programming practice, the function factory should be contained within its own dynamic-link library (DLL), with the actual functions referenced by the factory being in another DLL. This increases the performance of opening any toolbox that contains your new function tools.


See Also:

Sample: Building a custom geoprocessing function tool