ArcGIS Pro 3.0 API Reference Guide
ArcGIS.Desktop.Core.Geoprocessing Namespace / Geoprocessing Class / ExecuteToolAsync Method / ExecuteToolAsync(String,IEnumerable<String>,IEnumerable<KeyValuePair<String,String>>,Nullable<CancellationToken>,GPToolExecuteEventHandler,GPExecuteToolFlags) Method
Use toolboxalias.toolname, toolname_toolboxalias pattern or full path
Array of parameter values. Use MakeValueArray to pack all parameter values first.
Array of environment settings - each setting is a key-value pair of environment name and its value). Use MakeEnvironmentArray first to pack all environments.
A CancellationToken object.
Execute event delegateGPToolExecuteEventHandler(optional)
flags = GPExecuteToolFlags.Default (AddOutputsToMap | RefreshProjectItems) GPExecuteToolFlags
Example

ExecuteToolAsync(String,IEnumerable<String>,IEnumerable<KeyValuePair<String,String>>,Nullable<CancellationToken>,GPToolExecuteEventHandler,GPExecuteToolFlags) Method
Executes a geoprocessing tool.
Syntax

Parameters

toolPath
Use toolboxalias.toolname, toolname_toolboxalias pattern or full path
values
Array of parameter values. Use MakeValueArray to pack all parameter values first.
environments
Array of environment settings - each setting is a key-value pair of environment name and its value). Use MakeEnvironmentArray first to pack all environments.
cancelToken
A CancellationToken object.
callback
Execute event delegateGPToolExecuteEventHandler(optional)
flags
flags = GPExecuteToolFlags.Default (AddOutputsToMap | RefreshProjectItems) GPExecuteToolFlags

Return Value

A Task of type IGPResult. See IGPResult for more information.
Remarks
This method is used to execute a geoprocessing tool. Additionally, you can also use the optional parameters to handle geoprocessing events.
Example
FieldMappings
var environment = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);

      var prj = Project.Current;
      var map = MapView.Active;

      var defaultGDB = Project.Current.DefaultGeodatabasePath;

      var featLayers = map.Map.Layers.OfType<FeatureLayer>();

      var targetLayer = featLayers.ElementAt(0);  // First layer in TOC
      var joinLayer = featLayers.ElementAt(1);    // Second layer in TOC

      var outputFeatureClass = @"C:/temp/outputFC3.shp";

      // Specify the field map in Spatial Join with target and join feature class/layers in the App
      // Run Spatial Join manually - then Copy the fieldmap string from the result in Geoprocessing history and paste it for the fieldmap parameter. 
      // in this example of fieldmap, FireStations is the name of join layer
      // FireStations layer has two numeric fileds (used in Fieldmap): TYPE and NUMBER - these two fields are used in the FiedlMap
      //
      var joinLayerName = joinLayer.Name;
      var fieldMap = "TYPE 'TYPE' true true false 4 Long 0 0,Count,#,{joinLayerName},TYPE,-1,-1;NUMBER 'NUMBER' true true false 4 Long 0 0,Max,#,{joinLayerName},NUMBER,-1,-1";

      var toolParameters = Geoprocessing.MakeValueArray(targetLayer, joinLayer, outputFeatureClass, "JOIN_ONE_TO_ONE", "KEEP_COMMON", fieldMap, "INTERSECT");

      GPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddOutputsToMap | GPExecuteToolFlags.GPThread | GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.RefreshProjectItems;

      IGPResult gpResult = await Geoprocessing.ExecuteToolAsync("analysis.SpatialJoin", toolParameters, environment, null, null, executeFlags);

      Geoprocessing.ShowMessageBox(gpResult.Messages, "GP Messages", gpResult.IsFailed ? GPMessageBoxStyle.Error : GPMessageBoxStyle.Default);
FieldMappings
var environment = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);

      var prj = Project.Current;
      var map = MapView.Active;

      var defaultGDB = Project.Current.DefaultGeodatabasePath;

      var featLayers = map.Map.Layers.OfType<FeatureLayer>();

      var targetLayer = featLayers.ElementAt(0);  // First layer in TOC
      var joinLayer = featLayers.ElementAt(1);    // Second layer in TOC

      var outputFeatureClass = @"C:/temp/outputFC3.shp";

      // Specify the field map in Spatial Join with target and join feature class/layers in the App
      // Run Spatial Join manually - then Copy the fieldmap string from the result in Geoprocessing history and paste it for the fieldmap parameter. 
      // in this example of fieldmap, FireStations is the name of join layer
      // FireStations layer has two numeric fileds (used in Fieldmap): TYPE and NUMBER - these two fields are used in the FiedlMap
      //
      var joinLayerName = joinLayer.Name;
      var fieldMap = "TYPE 'TYPE' true true false 4 Long 0 0,Count,#,{joinLayerName},TYPE,-1,-1;NUMBER 'NUMBER' true true false 4 Long 0 0,Max,#,{joinLayerName},NUMBER,-1,-1";

      var toolParameters = Geoprocessing.MakeValueArray(targetLayer, joinLayer, outputFeatureClass, "JOIN_ONE_TO_ONE", "KEEP_COMMON", fieldMap, "INTERSECT");

      GPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddOutputsToMap | GPExecuteToolFlags.GPThread | GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.RefreshProjectItems;

      IGPResult gpResult = await Geoprocessing.ExecuteToolAsync("analysis.SpatialJoin", toolParameters, environment, null, null, executeFlags);

      Geoprocessing.ShowMessageBox(gpResult.Messages, "GP Messages", gpResult.IsFailed ? GPMessageBoxStyle.Error : GPMessageBoxStyle.Default);
gp_environments
// get the syntax of the tool from Python window or from tool help page
string in_features = @"C:\data\data.gdb\HighwaysWeb84";
      string out_features = @"C:\data\data.gdb\HighwaysUTM";
      var param_values = Geoprocessing.MakeValueArray(in_features, out_features);

      // crate the spatial reference object to pass as an argument to management.CopyFeatures tool
      var sp_ref = await QueuedTask.Run(() => {
          return SpatialReferenceBuilder.CreateSpatialReference(26911);    // UTM 83 11N: 26911
      });

      // set output coordinate system environment           
      var environments = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: sp_ref);
      // set environments in the 3rd parameter
      var gp_result = await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", param_values, environments, null, null, GPExecuteToolFlags.AddOutputsToMap);
      
      Geoprocessing.ShowMessageBox(gp_result.Messages, "Contents", GPMessageBoxStyle.Default, "Window Title");

      //return gp_result;
gp_environments
// get the syntax of the tool from Python window or from tool help page
string in_features = @"C:\data\data.gdb\HighwaysWeb84";
      string out_features = @"C:\data\data.gdb\HighwaysUTM";
      var param_values = Geoprocessing.MakeValueArray(in_features, out_features);

      // crate the spatial reference object to pass as an argument to management.CopyFeatures tool
      var sp_ref = await QueuedTask.Run(() => {
          return SpatialReferenceBuilder.CreateSpatialReference(26911);    // UTM 83 11N: 26911
      });

      // set output coordinate system environment           
      var environments = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: sp_ref);
      // set environments in the 3rd parameter
      var gp_result = await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", param_values, environments, null, null, GPExecuteToolFlags.AddOutputsToMap);
      
      Geoprocessing.ShowMessageBox(gp_result.Messages, "Contents", GPMessageBoxStyle.Default, "Window Title");

      //return gp_result;
progress_dialog
var progDlg = new ProgressDialog("Running Geoprocessing Tool", "Cancel", 100, true);
      progDlg.Show();
      
      var progSrc = new CancelableProgressorSource(progDlg);

      // prepare input parameter values to CopyFeatures tool
      string input_data = @"C:\data\california.gdb\ca_highways";
      string out_workspace = ArcGIS.Desktop.Core.Project.Current.DefaultGeodatabasePath;
      string out_data = System.IO.Path.Combine(out_workspace, "ca_highways2");

      // make a value array of strings to be passed to ExecuteToolAsync
      var parameters = Geoprocessing.MakeValueArray(input_data, out_data);

      // execute the tool
      await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", parameters,
          null, new CancelableProgressorSource(progDlg).Progressor, GPExecuteToolFlags.Default);

      // dialog hides itself once the execution is complete
      progDlg.Hide();
progress_dialog
var progDlg = new ProgressDialog("Running Geoprocessing Tool", "Cancel", 100, true);
      progDlg.Show();
      
      var progSrc = new CancelableProgressorSource(progDlg);

      // prepare input parameter values to CopyFeatures tool
      string input_data = @"C:\data\california.gdb\ca_highways";
      string out_workspace = ArcGIS.Desktop.Core.Project.Current.DefaultGeodatabasePath;
      string out_data = System.IO.Path.Combine(out_workspace, "ca_highways2");

      // make a value array of strings to be passed to ExecuteToolAsync
      var parameters = Geoprocessing.MakeValueArray(input_data, out_data);

      // execute the tool
      await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", parameters,
          null, new CancelableProgressorSource(progDlg).Progressor, GPExecuteToolFlags.Default);

      // dialog hides itself once the execution is complete
      progDlg.Hide();
gp_events
System.Threading.CancellationTokenSource _cts;

string ozone_points = @"C:\data\ca_ozone.gdb\O3_Sep06_3pm";

string[] args = { ozone_points, "OZONE", "", "in_memory\\raster", "300",
                    "EMPIRICAL", "300", "5", "5000",
                    "NBRTYPE=StandardCircular RADIUS=310833.272442914 ANGLE=0 NBR_MAX=10 SECTOR_TYPE=ONE_SECTOR",
                    "PREDICTION", "0.5", "EXCEED", "", "K_BESSEL" };

string tool_path = "ga.EmpiricalBayesianKriging";

_cts = new System.Threading.CancellationTokenSource();

var result = await Geoprocessing.ExecuteToolAsync(tool_path, args, null, _cts.Token,
    (event_name, o) =>  // implement delegate and handle events
    {
        switch (event_name)
        {
            case "OnValidate": // stop execute if any warnings
                if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning))
                    _cts.Cancel();
                break;

            case "OnProgressMessage":
                string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o });
                System.Windows.MessageBox.Show(msg);
                _cts.Cancel();
                break;

            case "OnProgressPos":
                string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o });
                System.Windows.MessageBox.Show(msg2);
                _cts.Cancel();
                break;
        }
    });

var ret = result;
_cts = null;
message_box
var gp_result = await Geoprocessing.ExecuteToolAsync("management.GetCount", Geoprocessing.MakeValueArray(@"C:\data\f.gdb\hello"));
      // this icon shows up left of content_header
      string icon_src = @"C:\data\Icons\ModifyLink32.png";
      Geoprocessing.ShowMessageBox(gp_result.Messages, "Content Header", GPMessageBoxStyle.Error, "Window Title", icon_src);
message_box
var gp_result = await Geoprocessing.ExecuteToolAsync("management.GetCount", Geoprocessing.MakeValueArray(@"C:\data\f.gdb\hello"));
      // this icon shows up left of content_header
      string icon_src = @"C:\data\Icons\ModifyLink32.png";
      Geoprocessing.ShowMessageBox(gp_result.Messages, "Content Header", GPMessageBoxStyle.Error, "Window Title", icon_src);
How to execute a Model tool
// get the model tool's parameter syntax from the model's help
string input_roads = @"C:\data\Input.gdb\PlanA_Roads";
      string buff_dist_field = "Distance";   // use values from a field
      string input_vegetation = @"C:\data\Input.gdb\vegetation";
      string output_data = @"C:\data\Output.gdb\ClippedFC2";

      // the model name is ExtractVegetation
      string tool_path = @"C:\data\MB\Models.tbx\ExtractVegetation";

      var args = Geoprocessing.MakeValueArray(input_roads, buff_dist_field, input_vegetation, output_data);

      var result = await Geoprocessing.ExecuteToolAsync(tool_path, args);
How to execute a Model tool
// get the model tool's parameter syntax from the model's help
string input_roads = @"C:\data\Input.gdb\PlanA_Roads";
      string buff_dist_field = "Distance";   // use values from a field
      string input_vegetation = @"C:\data\Input.gdb\vegetation";
      string output_data = @"C:\data\Output.gdb\ClippedFC2";

      // the model name is ExtractVegetation
      string tool_path = @"C:\data\MB\Models.tbx\ExtractVegetation";

      var args = Geoprocessing.MakeValueArray(input_roads, buff_dist_field, input_vegetation, output_data);

      var result = await Geoprocessing.ExecuteToolAsync(tool_path, args);
Set Geoprocessing extent environment
var parameters = Geoprocessing.MakeValueArray(@"C:\data\data.gdb\HighwaysUTM11", @"C:\data\data.gdb\Highways_extent");
      var ext = Geoprocessing.MakeEnvironmentArray(extent: "460532 3773964 525111 3827494");
      var gp_result = await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", parameters, ext);
Set Geoprocessing extent environment
var parameters = Geoprocessing.MakeValueArray(@"C:\data\data.gdb\HighwaysUTM11", @"C:\data\data.gdb\Highways_extent");
      var ext = Geoprocessing.MakeEnvironmentArray(extent: "460532 3773964 525111 3827494");
      var gp_result = await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", parameters, ext);
Stop a feature class created with GP from automatically adding to the map
// However, settings in Pro App's Geoprocessing Options will override option set in code
// for example, in Pro App's Options > Geoprocessing dialog, if you check 'Add output datasets to an open map'
// then the output WILL BE added to history overriding settings in code
var CopyfeaturesParams = Geoprocessing.MakeValueArray("C:\\data\\Input.gdb\\PlanA_Roads", "C:\\data\\Input.gdb\\Roads_copy");
      IGPResult gpResult = await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", CopyfeaturesParams, null, null, null, GPExecuteToolFlags.None);
Stop a feature class created with GP from automatically adding to the map
// However, settings in Pro App's Geoprocessing Options will override option set in code
// for example, in Pro App's Options > Geoprocessing dialog, if you check 'Add output datasets to an open map'
// then the output WILL BE added to history overriding settings in code
var CopyfeaturesParams = Geoprocessing.MakeValueArray("C:\\data\\Input.gdb\\PlanA_Roads", "C:\\data\\Input.gdb\\Roads_copy");
      IGPResult gpResult = await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", CopyfeaturesParams, null, null, null, GPExecuteToolFlags.None);
GPExecuteToolFlags.AddToHistory will add the execution messages to Hisotry
// However, settings in Pro App's Geoprocessing Options will override option set in code
// for example, if in Options > Geoprocessing dialog, if you uncheck 'Write geoprocessing operations to Geoprocessing History'
// then the output will not be added to history.
var args2 = Geoprocessing.MakeValueArray("C:\\data\\Vegetation.shp", "NewField", "TEXT");
      var result2 = await Geoprocessing.ExecuteToolAsync("management.AddField", args2, null, null, null, GPExecuteToolFlags.AddToHistory);
GPExecuteToolFlags.AddToHistory will add the execution messages to Hisotry
// However, settings in Pro App's Geoprocessing Options will override option set in code
// for example, if in Options > Geoprocessing dialog, if you uncheck 'Write geoprocessing operations to Geoprocessing History'
// then the output will not be added to history.
var args2 = Geoprocessing.MakeValueArray("C:\\data\\Vegetation.shp", "NewField", "TEXT");
      var result2 = await Geoprocessing.ExecuteToolAsync("management.AddField", args2, null, null, null, GPExecuteToolFlags.AddToHistory);
Multi Ring Buffer
//The data referenced in this snippet can be downloaded from the arcgis-pro-sdk-community-samples repo
//https://github.com/Esri/arcgis-pro-sdk-community-samples
async Task<IGPResult> CreateRings(EditingTemplate currentTemplate)
      {
          var paramsArray = Geoprocessing.MakeValueArray(currentTemplate.MapMember.Name,
                      @"C:\Data\FeatureTest\FeatureTest.gdb\Points_MultipleRingBuffer",
                      new List<string> { "1000", "2000" }, "Meters", "Distance",
                      "ALL", "FULL");

          IGPResult ringsResult = await Geoprocessing.ExecuteToolAsync("Analysis.MultipleRingBuffer", paramsArray);
          var messages = string.IsNullOrEmpty(gpResult.ReturnValue)
                  ? $@"Error in gp tool: {gpResult.ErrorMessages}"
                  : $@"Ok: {gpResult.ReturnValue}";

          return ringsResult;
      }
Multi Ring Buffer
//The data referenced in this snippet can be downloaded from the arcgis-pro-sdk-community-samples repo
//https://github.com/Esri/arcgis-pro-sdk-community-samples
async Task<IGPResult> CreateRings(EditingTemplate currentTemplate)
      {
          var paramsArray = Geoprocessing.MakeValueArray(currentTemplate.MapMember.Name,
                      @"C:\Data\FeatureTest\FeatureTest.gdb\Points_MultipleRingBuffer",
                      new List<string> { "1000", "2000" }, "Meters", "Distance",
                      "ALL", "FULL");

          IGPResult ringsResult = await Geoprocessing.ExecuteToolAsync("Analysis.MultipleRingBuffer", paramsArray);
          var messages = string.IsNullOrEmpty(gpResult.ReturnValue)
                  ? $@"Error in gp tool: {gpResult.ErrorMessages}"
                  : $@"Ok: {gpResult.ReturnValue}";

          return ringsResult;
      }
Non-blocking execution of a Geoprocessing tool
//The data referenced in this snippet can be downloaded from the arcgis-pro-sdk-community-samples repo
//https://github.com/Esri/arcgis-pro-sdk-community-samples
string in_data = @"C:\tools\data.gdb\cities";
      string cities_buff = @"E:\data\data.gdb\cities_2km";

      var valueArray = Geoprocessing.MakeValueArray(in_data, cities_buff, "2000 Meters");

      // to let the GP tool run asynchronously without blocking the main thread
      // use the GPThread option of GPExecuteToolFlasgs
      //
      GPExecuteToolFlags flags = GPExecuteToolFlags.GPThread;  // instruct the tool run non-blocking GPThread
      IGPResult bufferResult = await Geoprocessing.ExecuteToolAsync("Analysis.Buffer", valueArray, null, null, null, flags);
Non-blocking execution of a Geoprocessing tool
//The data referenced in this snippet can be downloaded from the arcgis-pro-sdk-community-samples repo
//https://github.com/Esri/arcgis-pro-sdk-community-samples
string in_data = @"C:\tools\data.gdb\cities";
      string cities_buff = @"E:\data\data.gdb\cities_2km";

      var valueArray = Geoprocessing.MakeValueArray(in_data, cities_buff, "2000 Meters");

      // to let the GP tool run asynchronously without blocking the main thread
      // use the GPThread option of GPExecuteToolFlasgs
      //
      GPExecuteToolFlags flags = GPExecuteToolFlags.GPThread;  // instruct the tool run non-blocking GPThread
      IGPResult bufferResult = await Geoprocessing.ExecuteToolAsync("Analysis.Buffer", valueArray, null, null, null, flags);
How to pass parameter with multiple or complex input values
var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);

      string toolName = "Snap_edit";  // or use edit.Snap

      // Snap tool takes multiple inputs each of which has
      // Three (3) parts: a feature class or layer, a string value and a distance
      // Each part is separated by a semicolon - you can get example of sytax from the tool documentation page
      var snapEnv = @"'C:/SnapProject/fgdb.gdb/line_1' END '2 Meters';'C:/SnapProject/fgdb.gdb/points_1' VERTEX '1 Meters';'C:/SnapProject/fgdb.gdb/otherline_1' END '20 Meters'";

      var infc = @"C:/SnapProject/fgdb.gdb/poly_1";

      var snapParams = Geoprocessing.MakeValueArray(infc, snapEnv);

      GPExecuteToolFlags tokens = GPExecuteToolFlags.RefreshProjectItems | GPExecuteToolFlags.GPThread | GPExecuteToolFlags.AddToHistory;

      IGPResult snapResult = await Geoprocessing.ExecuteToolAsync(toolName, parameters, environments, null, null, tokens);

      //return gpResult;
How to pass parameter with multiple or complex input values
var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);

      string toolName = "Snap_edit";  // or use edit.Snap

      // Snap tool takes multiple inputs each of which has
      // Three (3) parts: a feature class or layer, a string value and a distance
      // Each part is separated by a semicolon - you can get example of sytax from the tool documentation page
      var snapEnv = @"'C:/SnapProject/fgdb.gdb/line_1' END '2 Meters';'C:/SnapProject/fgdb.gdb/points_1' VERTEX '1 Meters';'C:/SnapProject/fgdb.gdb/otherline_1' END '20 Meters'";

      var infc = @"C:/SnapProject/fgdb.gdb/poly_1";

      var snapParams = Geoprocessing.MakeValueArray(infc, snapEnv);

      GPExecuteToolFlags tokens = GPExecuteToolFlags.RefreshProjectItems | GPExecuteToolFlags.GPThread | GPExecuteToolFlags.AddToHistory;

      IGPResult snapResult = await Geoprocessing.ExecuteToolAsync(toolName, parameters, environments, null, null, tokens);

      //return gpResult;
Requirements

Target Platforms: Windows 11, Windows 10, Windows 8.1

ArcGIS Pro version: 2.0 or higher.
See Also