Skip To Content ArcGIS for Developers Sign In Dashboard

Overview

You will learn: how to build an add-in that runs a geoprocessing tool with input parameters. You will then use a Python script to process the output of your new add-in.

With the ArcGIS Pro SDK for .NET, you can extend ArcGIS Pro with your own unique tools and workflows. Using Microsoft Visual Studio and the Pro SDK, you can build Pro add-ins and configurations that provide custom functionality specific to their organization or industry. The Pro SDK provides the ability to execute geoprocessing tools as add-ins, with the option to return the output of geoprocessing tasks.

In this tutorial, you will create two buttons for a new add-in group. The first button will execute the Buffer_analysis geoprocessing tool and buffer a selected feature. The second button will run a Python script and buffer a set of points to create multiple feature classes.

Before you being

Install the Pro SDK community sample datasets. The python script you will write will require the FeatureTest dataset. As specified in the script, the input TestPoints feature class and path should be found at: C:\Data\FeatureTest\FeatureTest.gdb\TestPoints. If your sample data is located somewhere else, you will need to update the paths in the script.

Steps

Create a new ArcGIS Pro Add-In solution

  1. Start Visual Studio.

  2. Choose File > New > Project and then from the ArcGIS templates group, select ArcGIS Pro Module Add-in. Name the add-in project "RunGPTool". Click OK to proceed.

Add a button control to your add-in

  1. From the Solution Explorer, right click the project and choose Add > New Item. From the ArcGIS Pro Add-ins group select ArcGIS Pro Button. Name the new class file RunGP.cs and press Add to close the dialog box. The button template provides the contents of the class file, as well as the corresponding code in the Config.daml file for the Pro UI.

  2. Update the OnClick method of RunGP.cs so that it is async:

    protected override async void OnClick()
    
  3. Add the following code to the OnClick method of RunGP.cs:

                await QueuedTask.Run(async () =>
                {
                    // Check for an active mapview, if not, then prompt and exit.
                    if (MapView.Active == null)
                    {
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("No MapView currently active. Exiting...", "Info");
                        return;
                    }
                    // Get the layer(s) selected in the Contents pane, if there is not just one, then prompt then exit.
                    if (MapView.Active.GetSelectedLayers().Count != 1)
                    {
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("One feature layer must be selected in the Contents pane. Exiting...", "Info");
                        return;
                    }
                    // Check to see if the selected layer is a feature layer, if not, then prompt and exit.
                    var featLayer = MapView.Active.GetSelectedLayers().First() as FeatureLayer;
                    if (featLayer == null)
                    {
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("A feature layer must be selected in the Contents pane. Exiting...", "Info");
                        return;
                    }
    
                    try
                    {
                        // Get the path to the layer's feature class and path to a new 200-foot buffer feature class
                        string FLPath = featLayer.GetFeatureClass().GetDatastore().GetPath().AbsolutePath;
                        var FLPathCombine = System.IO.Path.GetFullPath(FLPath);
                        string infc = System.IO.Path.Combine(FLPathCombine, featLayer.Name);
                        string outfc = System.IO.Path.Combine(FLPathCombine, "Buffer_" + featLayer.Name);
                        // Place parameters into an array
                        var parameters = Geoprocessing.MakeValueArray(infc, outfc, "200 Feet");
                        // Place environment settings in an array, in this case, OK to over-write
                        var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);
                        // Execute the GP tool with parameters
                        var gpResult = await Geoprocessing.ExecuteToolAsync("Buffer_analysis", parameters, environments);
                        // Show a messagebox with the results
                        Geoprocessing.ShowMessageBox(gpResult.Messages, "GP Messages", gpResult.IsFailed ? GPMessageBoxStyle.Error : GPMessageBoxStyle.Default);
    
                    }
                    catch (Exception exc)
                    {
                        // Catch any exception found and display in a message box
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Exception caught while trying to run GP tool: " + exc.Message);
                        return;
                    }
                });
    

Add a second button control to your add-in

  1. From the Solution Explorer, right click the project and choose Add > New Item. From the ArcGIS Pro Add-ins group select ArcGIS Pro Button. Name the class "RunPython.cs". Press Add to close the dialog box. This button template provides the contents of the class file, as well as corresponding code in the Config.daml file for the Pro UI.

  2. Add the following code to the OnClick method in RunPython.cs:

                QueuedTask.Run(() =>
                {
                    try
                    {
                        // Inform user that add-in is about to call Python script.
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Click OK to start script, and wait for completion messagebox.", "Info");
                        // Create and format path to Pro
                        var pathProExe = System.IO.Path.GetDirectoryName((new System.Uri(Assembly.GetEntryAssembly().CodeBase)).AbsolutePath);
                        if (pathProExe == null) return;
                        pathProExe = Uri.UnescapeDataString(pathProExe);
                        pathProExe = System.IO.Path.Combine(pathProExe, @"Python\envs\arcgispro-py3");
                        // Create and format path to Python
                        var pathPython = System.IO.Path.GetDirectoryName((new System.Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath);
                        if (pathPython == null) return;
                        pathPython = Uri.UnescapeDataString(pathPython);
                        // Create and format process command string.
                        // NOTE:  Path to Python script is below, "C:\temp\RunPython.py", which can be kept or updated based on the location you place it.
                        var myCommand = string.Format(@"/c """"{0}"" ""{1}""""",
                            System.IO.Path.Combine(pathProExe, "python.exe"),
                            System.IO.Path.Combine(pathPython, @"C:\temp\RunPython.py"));
                        // Create process start info, with instruction settings
                        var procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", myCommand);
                        procStartInfo.RedirectStandardOutput = true;
                        procStartInfo.RedirectStandardError = true;
                        procStartInfo.UseShellExecute = false;
                        procStartInfo.CreateNoWindow = true;
                        // Create process and start it
                        System.Diagnostics.Process proc = new System.Diagnostics.Process();
                        proc.StartInfo = procStartInfo;
                        proc.Start();
                        // Create and format result string
                        string result = proc.StandardOutput.ReadToEnd();
                        string error = proc.StandardError.ReadToEnd();
                        if (!string.IsNullOrEmpty(error)) result += string.Format("{0} Error: {1}", result, error);
                        // Show result string
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(result, "Info");
                    }
    
                    catch (Exception exc)
                    {
                        // Catch any exception found and display in a message box
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Exception caught while trying to run Python tool: " + exc.Message);
                        return;
                    }
                });
    

Update the Config.daml file

  1. Update the Config.daml file AddInInfo section so that the DAML appears as follows:

    </AddInInfo>
    <modules>
        <insertModule id="RunGPTool_Module" className="Module1" autoLoad="false" caption="Module1">
        <groups>
            <group id="RunGPTool_Group1" caption="Run GP and Python" appearsOnAddInTab="true">
            <button refID="RunGPTool_RunGP" size="large" />
            <button refID="RunGPTool_RunPython" size="large" />
            </group>
        </groups>
        <controls>
            <button id="RunGPTool_RunGP" caption="Run GP Tool" className="RunGP" loadOnClick="true" smallImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonBlue16.png" largeImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonBlue32.png">
            <tooltip heading="Run a GP Tool">Runs the Buffer GP Tool on the selected feature layer.<disabledText /></tooltip>
            </button>
            <button id="RunGPTool_RunPython" caption="Run Python Script" className="RunPython" loadOnClick="true" smallImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonBlue16.png" largeImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonBlue32.png">
            <tooltip heading="Run a Python Script">Run a Python script to buffer features in the FeatureTest sample dataset.<disabledText /></tooltip>
            </button>
        </controls>
        </insertModule>
    </modules>
    

The above updates the captions and tooltips for each of the buttons, and the control group, which will appear on the Add-In tab.

Create a Python script file

  1. The RunPython.cs OnClick method you created will run a Python script which you will now create. Create a new text file named RunPython.py in the folder C:\temp on your machine. Place the following code in this script file, and save the file.

    import arcpy
    arcpy.env.overwriteOutput = True
    
    # Note: Script assumes data from Pro SDK community samples are installed under C:\Data, as follows:
    inFC = "C:\Data\FeatureTest\FeatureTest.gdb\TestPoints"
    outFCBuffer300 = "C:\Data\FeatureTest\FeatureTest.gdb\TestPoints_Buffer_300ft"
    outFCBuffer400 = "C:\Data\FeatureTest\FeatureTest.gdb\TestPoints_Buffer_400ft"
    outFCBuffer500 = "C:\Data\FeatureTest\FeatureTest.gdb\TestPoints_Buffer_500ft"
    
    # Buffer the input features creating three buffer distance feature classes
    arcpy.Buffer_analysis(inFC, outFCBuffer300, "300 feet")
    arcpy.Buffer_analysis(inFC, outFCBuffer400, "400 feet")
    arcpy.Buffer_analysis(inFC, outFCBuffer500, "500 feet")
    
    # The following message will be included in the message box from the calling button's OnClick routine
    print("Buffer routine from Python script complete. \r\n View and add 300-, 400- and 500-foot buffer feature classes from the Catalog pane.")
    
  2. A requirement for running the Python script as currently written in the above step is that you must have the Pro SDK community sample datasets installed, in particular the FeatureTest dataset. As specified in the script, the input TestPoints feature class and path should be found at: C:\Data\FeatureTest\FeatureTest.gdb\TestPoints.

    Note: If you installed the FeatureTest sample dataset in a different location, you will need to update the paths to the file geodatabase within your Python script from the prior step.

Test your add-in

  1. Build your project and debug any issues. Start your Visual Studio project which will launch ArcGIS Pro. Open the FeatureTest.aprx project installed under C:\Data\FeatureTest\, or the location where you installed it. Once the project opens, click on the Add-In tab and find your new control group with your two new buttons.

  2. To test the Run GP Tool button, select the TestPoints feature layer from the project. Click on the Run GP Tool button, and wait for the GP message box to appear with results.

  3. To test the Run Python Script button, press the button. When the process is completed, confirm that the new buffer feature classes were created in the file geodatabase. You can view and add these to your project using the Catalog pane. You may need to refresh the view of the file geodatabase to see the new feature classes.

Congratulations, you're done!

Compare your solution with our completed solution project.

Challenge

Review the online documentation

Read more about working with the Geoprocessing API in the document ProConcepts Geoprocessing.

Try a community sample

Try some of the Geoprocessing topic community samples on GitHub.