ProConcepts Geoprocessing - kataya/arcgis-pro-sdk GitHub Wiki
The geoprocessing public APIs are exposed through the ArcGIS.Desktop.Core.Geoprocessing namespace in the ArcGIS Pro API Reference Guide. The core useful methods, enumerators, and interfaces for geoprocessing tasks are available in this namespace.
ArcGIS.Desktop.Core.Geoprocessing.dll
Language: C#
Subject: Geoprocessing
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: Esri, http://www.esri.com
Date: 11/24/2020
ArcGIS Pro: 2.7
Visual Studio: 2017, 2019
The Geoprocessing API available in the ArcGIS.Desktop.Core.Geoprocessing namespace is all about how to perform analysis in ArcGIS Pro using .NET. It exposes methods to execute any geoprocessing tool.
To use the Geoprocessing API, you first need to create an add-in that executes code involving ExecuteToolAsync in response to an event (for example, Button Click) triggered by interacting with the add-in.
Use the ExecuteToolAsync method to run any geoprocessing tool (including a Python script tool and models). The code of the add-in can use map layers, geometry created on the fly, or data stored on disk as input for analysis. You can provide paths to data to the geoprocessing tool, or open the tool dialog in the Geoprocessing pane of ArcGIS Pro and let the user provide the parameter values and execute the tool.
Each geoprocessing tool takes a set of input data of various types—such as feature class, table, geometry, workspace, spatial reference, and so on—and in most cases, creates new data as output. Refer to the tool's help page to learn about the tool's behavior and to get appropriate data types and acceptable values of input and output parameters.
ExecuteToolAsync has an overload; both methods require the path of the tool to be executed and all inputs and output packed in an array. The input-output parameter values are positional; you must maintain the same position and sequence as specified on the tool help page.
In ArcGIS Pro, you can no longer create your own custom geoprocessing tool in .NET. However, you can create a tool using Python script and call it in .NET code.
If you need to run a sequence of tools with inputs from the users between the calls, create a model with the sequence setting appropriate model parameters, and call this model tool in your code.
Follow these preparatory steps before calling ExecuteToolAsync to avoid pitfalls and simple mistakes.
Note down the following:
- Tool name and toolbox alias. Both are case sensitive.
- Syntax for the correct parameter sequence. Note which parameters are required and which are optional.
- Data types and acceptable values to be supplied for the parameters. In .Net, you can always pass a string for a parameter value. You can also pass native .Net objects for some Supported native objects as parameter values.
- Names of the environments honored by the tool.
- Example of using the tool by examining the Python code samples.
Use the MakeValueArray method to create an array to be passed to the ExecuteToolAsync method. Using MakeValueArray ensures that the parameter values are properly handled by ExecuteToolAsync. The following is a code example of creating an array of parameter values:
// the tool to be executed has workspace as first parameter
// feature class name as second and feature type as third parameter
string outpath = Project.Current.DefaultGeodatabasePath;
string fcname = "accident_sites";
var sr = await QueuedTask.Run(() => {
return SpatialReferenceBuilder.CreateSpatialReference(3857);
});
// must maintain the sequence and position of each parameter value
var parameters = Geoprocessing.MakeValueArray(outpath, fcname, "POINT", "", "", "", sr);
To set one or more environments to be honored by the execution of the tool, use MakeEnvironmentArray as shown in the following code snippet:
// create the spatial reference object
var sp_ref = await QueuedTask.Run(() => {
return SpatialReferenceBuilder.CreateSpatialReference(26911); // UTM 83 11N: 26911
});
// create an extent object
var ext = "460532 3773964 525111 3827494";
// follow syntax env_name: env_value
// environment names will be available in the intellisense
var environments = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: sp_ref, extent: ext);
Note: Each geoprocessing tool honors specific environments. See the tool help page to find out which environments are honored by the tool. However, setting an environment that the tool does not honor will be ignored by the ExecuteToolAsync method.
In many scenarios, passing a Layer, geometry created while interacting with the map, Envelope or Extent, SpatialReference or a Table as an argument to a geoprocessing tool may be necessary. The following .Net types are supported and can be passed as parameter value:
- Scalars – long, short, float, double, date, string
- ArcGIS.Core.Geometry.SpatialReference
- ArcGIS.Core.Geometry – point, line, polygon
- ArcGIS.Core.Geometry.Envelope – supporting GP types of GPExtentEnv, GPExtent, GPEneveope
- ArcGIS.Core.Data.Field – supporting GPField and list of fields for GPFieldList
- ArcGIS.Desktop.Mapping – Layer, StandaloneTable
- ArcGIS.Core.Data.Dataset – Table, FeatureClass
// example of using ArcGIS.Core.Geometry.SpatialReference object
var spatial_ref = await QueuedTask.Run(() => {
return SpatialReferenceBuilder.CreateSpatialReference(3857);
});
// call MakeValueArray on spatial_ref so that ExecuteToolAsync can internally use the object
var sr_param = Geoprocessing.MakeValueArray(spatial_ref);
ExecuteToolAsync is overloaded; there are two methods having the same name with different parameter signature. To handle geoprocessing events, use ExecuteToolAsync with a parameter of type GPToolExecuteEventHandler. To show the progressor dialog, use the one with a parameter of type CancelableProgressor.
One of the overloaded ExecuteToolAsync methods has a delegate parameter of type GPToolExecuteEventHandler. To handle various events—such as OnValidate, OnProgressMessage, OnBeginExecute, OnProgressPos, OnBeginExecute, and OnEndExecute—pass a callback (for the fifth parameter) as shown in the following code example:
// code in the implementing method that Button's OnClick can call
string ozone_points = @"C:\data\ca_ozone.gdb\MarchValues";
var args = Geoprocessing.MakeValueArray(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";
// cancellation token variable is declared as a class member
System.Threading.CancellationTokenSource _cts = new System.Threading.CancellationTokenSource();
var result = Geoprocessing.ExecuteToolAsync(tool_path, args, null, _cts.Token,
(event_name, o) => // implement delegate and handle events, o is message object.
{
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;
}
});
This example uses CancelableProgressorSource with a Cancel option so that a user can terminate the execution before it completes.
protected override async void OnClick()
{
var progDlg = new ProgressDialog("Running Geoprocessing Tool", "Cancel", 100, true);
progDlg.Show();
var progSrc = new CancelableProgressorSource(progDlg);
string infc = @"D:\data\california\california.gdb\ca_highways";
string outfc = System.IO.Path.Combine(ArcGIS.Desktop.Core.Project.Current.DefaultGeodatabasePath, "Clipped_points");
var parameters = Geoprocessing.MakeValueArray(infc, outfc);
await Geoprocessing.ExecuteToolAsync("management.CopyFeatures", parameters,
null, new CancelableProgressorSource(progDlg).Progressor, GPExecuteToolFlags.Default);
progDlg.Hide();
}
Creating your own geoprocessing custom tool using .NET is no longer available. However, you can create your custom tool in Python leveraging the power of an ArcPy package. You can also create a model by knitting together a series of systems tools and calling the model tool in .NET.
Pass the full path of the script tool or model. Follow the preparatory steps previously described. Be sure to get the tool's syntax from its documentation.
// 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 the distance values from a field named Distance
string input_vegetation = @"C:\data\Input.gdb\vegtype";
string output_data = @"C:\data\Output.gdb\ClippedFC2";
string tool_path = @"C:\data\CompletedModels.tbx\ExtractVegetationforProposedRoads";
var args = Geoprocessing.MakeValueArray(input_roads, buff_dist_field, input_vegetation, output_data);
return Geoprocessing.ExecuteToolAsync(tool_path, args);
First create an *.ags file in ArcGIS Pro, and pass the full path of the service.
// pass the full path of the service
string tool_path = @"C:\data\agsonline.ags\Network/ESRI_DriveTime_US\CreateDriveTimePolygons";
string in_point = @"C:\MyProject\MyProject.gdb\apoint";
var result = await Geoprocessing.ExecuteToolAsync(tool_path, Geoprocessing.MakeValueArray(in_point, "3 9 12"));
The type of the last parameter of the ExecuteToolAsync method is GPExecuteToolFlags. Use one of the following values as needed. Using GPExecuteToolFlags.Default adds outputs to map and refreshes project items.
GPExecuteToolFlags.AddOutputsToMap
GPExecuteToolFlags.AddToHistory
GPExecuteToolFlags.RefreshProjectItems
GPExecuteToolFlags.Default
The OpenToolDialog method opens the tool dialog in the Geoprocessing pane, allowing the user to enter the input values and run the tool manually. You can fill in the parameter values calculated within the add-in code before opening the tool dialog, open the dialog, and let the users fill in the other values. The following are three examples:
This code opens the Buffer dialog with all three required values filled in:
string input_points = @"C:\data\ca_ozone.gdb\ozone_points";
string output_polys = @"C:\data\ca_ozone.gdb\ozone_buff";
string buffer_dist = "2000 Meters";
var param_values = Geoprocessing.MakeValueArray(input_points, output_polys, buffer_dist);
Geoprocessing.OpenToolDialog("analysis.Buffer", param_values);
This code opens the Buffer dialog with the first two parameter values filled in:
string input_points = @"C:\data\ca_ozone.gdb\ozone_points";
string output_polys = @"C:\data\ca_ozone.gdb\ozone_buff";
string buffer_dist = "";
var param_values = Geoprocessing.MakeValueArray(input_points, output_polys, buffer_dist);
Geoprocessing.OpenToolDialog("analysis.Buffer", param_values);
This code opens the Buffer dialog with no value for any of the parameters, letting the user have full control over what values to use:
string input_points = "";
string output_polys = "";
string buffer_dist = "";
var param_values = Geoprocessing.MakeValueArray(input_points, output_polys, buffer_dist);
Geoprocessing.OpenToolDialog("analysis.Buffer", param_values);
You can determine whether the execution was successful or not by examining the IGPResult object. The following code checks whether the execution failed by checking if gp_result.IsFailed is true or not.
You can get the geoprocessing messages from the result object as shown below:
// gp_result is the returned result object from a call to ExecuteToolAsync
// displays error messages if the tool fails, otherwise shows the default messages
Geoprocessing.ShowMessageBox(gp_result.Messages, "GP Messages",
gp_result.IsFailed ? GPMessageBoxStyle.Error : GPMessageBoxStyle.Default);
The test1.py script (in C:\scripts folder) runs a geoprocessing tool and returns messages as a string. In .NET, you can intercept that value and use it. This mechanism offers a way to implement workflows in a simpler, yet powerful ArcPy module's methods and functions, and use them in .NET.
object myCommand = "python " + @"C:\scripts\test1.py";
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c" + myCommand );
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
System.Windows.MessageBox.Show(result);