How to create a script tool that runs an EXE


Summary
This topic shows how to create a script tool using an executable (*.EXE) as its source.


About script tools

Many programs are written for specific datasets and scenarios. One of the advantages of programming is its flexibility to perform additional operations not provided by Esri and to extend the ArcGIS framework. Some programs perform a generic operation that can be used repeatedly because they use arguments to change tool parameters and behavior.
ArcGIS users are able to use the geoprocessing framework to create tools where program executables are used as the source. These types of tools are called script tools. By turning your executable into a tool, you can use them like system tools, for example, use it in a sequence of tasks in ModelBuilder or scripting.
Successful tool creation requires planning and design. You must first create a prototype and define the workflow before you create your tool. You need to integrate the following major steps when creating a script tool:
  1. Use the script tool wizard to define the parameters, which automatically creates a tool dialog box for you.
  2. Create an executable that can interact with the tool via the parameters. You set the executable as the source of the tool in step 1.

Laying out the tool design

Assume you have two sets of points. The first set represents major street nodes of an area (these points represent a geographic space). The second set of points is obtained through some functional relationship, which can be termed as functional space. To find the relationship between them, the functional space requires a spatial adjustment so that it is aligned with geographic space. To keep the creating executable part simple, the functional space is only passed through Affine Transformation. Finally, the transformed locations of points are stored in a new output. 

Creating the tool dialog box and defining parameters

The executable function requires two input feature classes as arguments and returns the created feature class as output. To accommodate this requirement, the script tool will have the following parameters:
  • Input Reference Features
  • Input Adjust Features
  • Output Adjusted Feature Class
  1. To create a script tool, right-click a custom toolbox and select Script from the Add menu. For more information, see Adding a script tool.
  2. Set your EXE instead of a Python script as the source of your tool.

The following screen shot shows how the parameters are set on the script tool wizard where the name of the script tool is Affine Transformation. Click the parameter name to view its properties on the Parameter Properties area. All three parameters are required. The direction of the first two is input and the third is output.
A script tool with an EXE as the source always runs out-of-process; thus, it is slower than a Python script tool.

Creating the executable

Create a Visual Studio console application. You can write all of your code in the Main method if the code is simple, or you can write several functions for better organization if the code is complex. The following is a summary of the required steps to develop the executable:
  1. Get the parameter values.
  2. Use parameter values for processing.
  3. Set messages and errors.
  4. Handle exceptions.
  5. Return the output by setting the output parameter value.

Using script tool parameters

Geoprocessing tools typically have parameters. Parameters or arguments make programs more generic and flexible so they can be used to vary input data, set other tool parameters used in the program, or control the program's processing logic. 
When a program is added to a toolbox as a script tool, various parameters can be defined. These parameters correspond to a program's parameters representing input and output values. 
Typically, programs only have input values, since they are usually run in an independent fashion. Script tools must define their outputs so tools work as expected in models built with ModelBuilder or on the Python Window of ArcGIS for Desktop. Models need an output parameter so they can be used as input for other tools, while tools on the command line allow users to specify the name and location of a tool's output.
Out-of-the-box system tools that ship with ArcGIS populate the properties of output variables in a model to aid subsequently connected tools. These properties are not required for building models but aid in their construction. System tools do this with a validation routine that is called each time a parameter value is changed for a tool. Script tools do not have a validation routine, just one for execution, which is the script or the executable.
The geoprocessing framework does some validation for script tools automatically, such as ensuring that a parameter value matches what is expected for a parameter, including a number for a numeric parameter and a path to a feature class for a feature class parameter. By defining dependencies between parameters, certain behavior can also be built into a tool. For example, a dependency between a feature class parameter and a field parameter, in which the field parameter is dependent on the feature class, means the field list automatically populates on the tool when the feature class is given a valid value using the Tool Validator class.
Another program might not actually have a new output because it alters a dataset specified as an input parameter. In this case, the script tool would still declare an output parameter, with the type set to derive with a dependency on the input dataset. The script tool automatically sets the output parameter's value to be the same as the input dataset when used in a model so the tool can be used in a workflow.
For more information, see Customizing script tool behavior.

Getting input parameter values

Programming languages typically provide a mechanism for accessing arguments passed to the program from the caller. If a program is the source of a script tool, it can use the geoprocessor to access the input parameter values. The following code example demonstrates how to use the GetParameterValue method to get input parameter values:
[C#]
public void ExampleGPSettingEnvironmentValues2(IGeoProcessor2 GP)
{

    // Get the input workspace environment value.
    object workspace = GP.GetParameterValue(0);
    GP.SetEnvironmentValue("workspace", (string)workspace);

    //TODO: Add your code here...

}
[VB.NET]
'Public Sub ExampleGPSettingEnvironmentValues2(ByVal GP As IGeoProcessor2)

' Get the input workspace environment value.
Dim workspace As Object = GP.GetParameterValue(0)
GP.SetEnvironmentValue("workspace", CStr(workspace))

'TODO: Add your code here...

End Sub

Setting output parameter values

Output parameter values might not be known until the program is executed. The program must evaluate or calculate an output value based on its input; therefore, script tools must have a way to specify output values after execution so the values can be used in a model workflow.
The SetParameterValue method sets the value of an output parameter using an object, such as a value table or text string. An index value is required to indicate which parameter will be updated. See the following code example:
[C#]
public void ExampleGPSettingOutputParameters(IGeoProcessor2 GP)
{
    // Check the feature classes and set the output parameters.
    GP.SetEnvironmentValue("workspace", (string)GP.GetParameterValue(0));
    if (GP.ListFeatureClasses("*", "POLYGON", "").Next() != null)
    {
        GP.AddMessage("Feature type is polygon");
        GP.SetParameterValue(0, (object)"true");
        GP.SetParameterValue(1, (object)"false");
    }
    else if (GP.ListFeatureClasses("*", "POLYLINE", "").Next() != null)
    {
        GP.AddMessage("Feature type is line");
        GP.SetParameterValue(0, (object)"false");
        GP.SetParameterValue(1, (object)"true");
    }
    else
    {
        GP.AddMessage("Coverage has neither polygons nor lines");
        GP.SetParameterValue(0, (object)"false");
        GP.SetParameterValue(1, (object)"false");
    }
    //TODO: Add your code here...
}
[VB.NET]
Public Sub ExampleGPSettingOutputParameters(ByVal GP As IGeoProcessor2)
    
    ' Check the feature classes and set the output parameters.
    GP.SetEnvironmentValue("workspace", CStr(GP.GetParameterValue(0)))
    
    If Not GP.ListFeatureClasses("*", "POLYGON", "").Next() Is Nothing Then
        
        GP.AddMessage("Feature type is polygon")
        GP.SetParameterValue(0, CObj("true"))
        GP.SetParameterValue(1, CObj("false"))
        
    ElseIf Not GP.ListFeatureClasses("*", "POLYLINE", "").Next() Is Nothing Then
        
        GP.AddMessage("Feature type is line")
        GP.SetParameterValue(0, CObj("false"))
        GP.SetParameterValue(1, CObj("true"))
        
    Else
        
        GP.AddMessage("Coverage has neither polygons nor lines")
        GP.SetParameterValue(0, CObj("false"))
        GP.SetParameterValue(1, CObj("false"))
        
    End If
    
    'TODO: Add your code here...
    
End Sub

Setting output messages

When a script tool is executed, messages often need to be returned to the user, especially when problems arise. To support the full integration of program executables as tools, the geoprocessor has several methods for adding messages that are then available to the user. Messages added to the geoprocessor are immediately returned to the application or program executing the tool. 
The following are the methods for adding various types of output messages:
  • AddMessage
  • AddWarning
  • AddError 
Each of these methods takes a single string parameter. Once an error message is added, the geoprocessor immediately generates a system error that halts the execution of the tool. The following code example copies a list of feature classes from one workspace to another. Error handling is used to catch any problems and return messages; otherwise, messages of success are returned during execution.
[C#]
public void ExampleSettingGPOutputMessages(Geoprocessor GP, Copy copyTool)
{

    // Identify feature classes and copy to file geodatabase.
    IGpEnumList fcs = GP.ListFeatureClasses("*", "", "");
    string fc = fcs.Next();

    while (fc != "")
    {

        GP.AddMessage("Copying " + fc + " to " + @"C:\NewData\nfld.gdb");
        copyTool.in_data = fc;
        copyTool.out_data = @"C:\NewData\nfld.gdb" + "\\" + fc;
        object sev = 2;

        try
        {

            GP.Execute(copyTool, null);

        }
        catch 
        {

            GP.AddError("Copy failed. " + GP.GetMessages(ref sev));

        }

        fc = fcs.Next();

    }

}
[VB.NET]
Public Sub ExampleSettingGPOutputMessages(ByVal GP As Geoprocessor, ByVal copyTool As Copy)
    
    ' Identify feature classes and copy to file geodatabase.
    Dim fcs As ESRI.ArcGIS.Geoprocessing.IGpEnumList = GP.ListFeatureClasses("*", "", "")
    Dim fc As String = fcs.Next()
    
    Do While fc <> ""
        
        GP.AddMessage("Copying " & fc & " to " & "C:\NewData\nfld.gdb")
        copyTool.in_data = fc
        copyTool.out_data = "C:\NewData\nfld.gdb" & "\" & fc
        Dim sev As Object = 2
        
        Try
        
        GP.Execute(copyTool, Nothing)
        
        Catch
        
        GP.AddError("Copy failed. " & GP.GetMessages(sev))
        
        End Try
        
        fc = fcs.Next()
        
    Loop
    
End Sub

Returning messages

There are times when you may want a script to return messages from a tool it has executed. Using an index parameter, the AddReturnMessage method returns a message from the geoprocessor's message array. The following code example shows how to return all of a tool's messages:
[C#]
public void ExampleGPReturningMessages(Geoprocessor GP, Copy copyTool)
{

    GP.Execute(copyTool, null);

    for (int Count = 0; Count <= GP.MessageCount - 1; Count++)
    {

        GP.AddReturnMessage(Count);

    }

}
[VB.NET]
Public Sub ExampleGPReturningMessages(ByVal GP As Geoprocessor, ByVal copyTool As Copy)
    
    GP.Execute(copyTool, Nothing)
    
    For Count As Integer = 0 To GP.MessageCount - 1
        
        GP.AddReturnMessage(Count)
        
    Next Count
    
End Sub

Handling exceptions

Debugging a script tool with an EXE as source is laborious. If a geoprocessing error occurs, you get back messages from the geoprocessor. If a system error or ArcObjects error occurs, an Exception is thrown. and if you do not handle it within the program, testing the tool will be very difficult. For more information, see Errors and exception handling in geoprocessing and Working with result objects.

Testing the tool

The basic test is to run the tool from a Catalog window. To make the tool usable, you must also test the tool in ModelBuilder and in a Python Window, and possibly in another Python or .NET application. If you want to share your tool, see A structure for sharing tools in the ArcGIS Desktop Help system.


See Also:

Customizing script tool behavior
Why create your own tools?