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:
Name property—This is the name of the function tool. This name appears when executing the tool at the command line or in scripting. This name should be unique to each toolbox and must not contain spaces.
DisplayName property—This is the display name of the function tool. The user interface (UI) utilizes this property to display the name of the tool in ArcToolbox. This name is a user-friendly description of the function tool. This display name can be internationalized.
FullName property—This is the function name object for the geoprocessing function tool. This name object is created and returned by a function factory. A function factory must be created before implementing this property.
HelpFile property (optional)—This is the path to a .chm file, which is used to describe and explain the function and its operation.
MetadataFile property (optional)—This is the name of the .xml file containing the default metadata for this function object. The metadata file is used to supply the parameter descriptions in the help panel on the dialog box. If no .chm file is provided, the help is based on the metadata file.
IsLicensed method—This is used to return whether the function tool is licensed to execute.
DialogCLSID property (optional)—This is the class identifier (CLSID) used to override the default dialog box for a tool. By default, the toolbox will create a dialog box based on the parameters returned by the ParameterInfo property.
ParameterInfo property—This is the location where the parameters to the function tool are defined. This property returns an IArray of parameter objects (IGPParameter). These objects define the characteristics of the input and output parameters.
Validate() method—This method checks that a given set of parameter values are of the appropriate number, DataType, and Value.
Execute() method—This method executes the tool given the array of parameter values.
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:
Name—The name of the parameter, for example, input_featureclass. It must not contain spaces.
DisplayName—The UI uses this name to display the parameter name, for example, Input Features. This can be internationalized.
Enabled—Controls whether this parameter is enabled or disabled on the UI.
ParameterType—This is the enumeration for setting the type of geoprocessing parameter. The following are the three parameter types: esriGPParameterTypeRequired, esriGPParameterTypeOptional, and esriGPParameterTypeDerived.
Direction—This is the enumeration for setting the direction of the parameter. The options are esriGPParameterDirectionInput or esriGPParameterDirectionOutput.
DataType—This property defines the type of data for this parameter. Some examples include FeatureClass, Raster, Table, String, and so on. DataType manages the value for the parameter. If the DataType is a FeatureClass, a Raster cannot be entered as input.
The following illustration shows some of the different data types and provides a code sample of creating a new FeatureClass parameter:
Value—This property defines the default value for a parameter. For every DataType, there is an associated value. If the DataType is a FeatureClass, the default value for the parameter is a FeatureClass. Values are used as the actual inputs to the tool containing scalars or a path to the data. For a complete list of Value objects, see IGPValues.
Domain (optional)—The Domain property can be specified to limit or filter a set of values. An example of this is a domain for a simple value object, limiting an integer to a range of 1 to 100 (RangeDomain).
ParameterDependencies (optional)—The ParameterDependencies property is used to set one parameter dependent on another parameter. As an example, a field parameter is commonly dependent on another table or feature class parameter, for example, list of fields is dependent on the input table.
ControlCLSID (optional)—A class identifier can be used to override the default control for the DataType.
Category (optional)—This property creates a collapsible section on the tool dialog box. This is useful for tools with many optional parameters.
DefaultEnvironmentName (optional)—This property initializes the environment value to use as the default environment for a parameter.
DisplayOrder (optional)—This is the order in which the parameters are listed on the dialog box. The usage display order is always the order in the array. In the ParameterInfo property, the parameters should be ordered by required, optional, and derived.
Altered—This property indicates whether the parameter has been explicitly set by the user.
HasBeenValidated—This property indicates whether the parameter value has been modified since the last time the parameter was validated.
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:
Basic validation—Basic validation of the parameter values is accomplished by calling a method on IGPUtilities called InternalValidate(). InternalValidate() tests the validity of a set of values against the set of parameters. This method checks whether all the required parameter values have been supplied, the parameter values are of the correct data type, and the input exists. However, if the input value is derived, meaning it is input to another tool in ModelBuilder, then its existence is not checked. This is accomplished by setting the honorDerivedFlag option for InternalValidate() to true.
Complex parameter interaction—For some tools, it may be necessary to set rules for parameters. For example, when adding a field to an input table, one rule may be to limit the length of the field name by setting a maximum number of allowable characters. Another example of parameter interaction is enabling and disabling parameters. For instance, when using Add Field and selecting TEXT as the type of field to add, the field length parameter is enabled. Another argument to Validate() is updateValues. When set to true, Validate() can modify parameter value properties; for example, setting the default value of a parameter or enabling or disabling a parameter.
Populate properties of the output parameter—If updateValues is true, the function should populate the properties of the output value. This is important for proper chaining of tools in ModelBuilder. The AddField tool is a good example. Add this tool to ModelBuilder and fill in its parameters. Then connect the output of AddField as input to another process such as Calculate Field. You now see the new field even though the model has not yet been executed. The sample tool associated with this topic adds a new field and provides an example of updating the output parameter.
The following sample tool illustrates how the output parameter value is updated. A field is added to the input shapefile. To ensure that this field is visible to other tools in ModelBuilder without this tool being executed first, you must clone the input table value and populate this new table value with the new field. The following code example is used in this sample tool:
[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
IfNot (inputTable IsNothing) ThenDim areaField As IField = m_GPUtilities.FindField(outputValue, m_Field)
If areaField IsNothingThenDim 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
EndIf
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:
Call Validate()—During Execute(), all input data must exist. To ensure that the input data exists and the parameter values are still valid, Validate() must be called. When calling the Validate() method in Execute(), ensure the Boolean arguments to InternalValidate() for updateValues and honorDerivedFlag are false to ensure newly created data exists.
Open Datasets—Opening the input datasets means creating objects from the inputs. For example, if the input value is a path to a feature class, try to create an IFeatureClass object. This ensures that this data still exists and is not locked by another application. The same is true for other inputs such as fields.
Checking the OverwriteOutput setting—If your tool creates new output data, you must check if the OverwriteOutput setting is true or false. If the setting is true, it is necessary to delete that existing output before performing the operation. The following code example shows how to check for the OverwriteOutput setting:
[C#]
// Check if OverWrite setting is set.
IGeoProcessorSettings settings = (IGeoProcessorSettings)envMgr;
if (settings.OverwriteOutput)
if (m_GPUtilities.Exists(parameterValue))
m_GPUtilities.Delete(parameterValue);
elseif (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 ThenIf m_GPUtilities.Exists(parameterValue) Then
m_GPUtilities.Delete(parameterValue)
ElseIf m_GPUtilities.Exists(parameterValue) Then
message.AddError(2, "Output already exists.")
ReturnEndIfEndIfEndIf
Execute the function—Executes the code to perform the operation.
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:
UnPackGPValue()—This method gets the value from the parameter and creates a GPValue object.
PackGPValue()—This method places the GPValue object into the parameter.
Exists()—Returns whether the input value exists or not.
OpenDataset()—Opens the data source associated with the value.
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.
CLSID property—This is the class identifier of the factory.
Name property—This is the name of the function factory that is used when generating the toolbox containing the function tools of the factory; it can be internationalized.
Alias property—This is the alias name of the factory. It is used when specifying the functions contained in the factory from the command line or scripting.
GetFunction() method—This method creates and returns a function object based on the input name.
GetFunctionName() method—This method creates and returns a function name object based upon the input name.
GetFunctionNames() method—This method creates and returns an enumeration of function names that the factory supports.
GetFunctionEnvironments() method (optional)—This method creates and returns an enumeration of GPEnvironment objects. If tools published by this function factory requires new environment settings, define the additional environment settings here. This is similar to how parameters are defined.