This document is archived and information here might be outdated.  Recommended version.


Using ArcObjects as tool input (ArcObjects .NET 10.8 SDK)
ArcObjects Help for .NET developers > ArcObjects Help for .NET developers > Developing with ArcGIS > Learning ArcObjects > Using geoprocessing > Executing tools > Using ArcObjects as tool input

Using ArcObjects as tool input


Summary
As discussed in the topic The role of geoprocessing in developing applications, one common misconception is that geoprocessing tools can only deal with pathname strings for feature data. This topic shows how to use interface objects such as IFeatureClass, IName, workspace, spatial reference, and other ArcObjects as tool input.

In this topic


Using ArcObjects reference

The ArcObjects that can be passed to a parameter depends on the parameter of the tool. Specific information of a parameter can be found in the tool's reference page. See Using a tool reference page for more information.
IFeatureClass, ILayer, IName, and IDataset objects can be used to define the input to any tool that accepts a feature class or feature layer. Additionally, an IRasterDataset object can be used as input to any tool that accepts a raster dataset or raster layer. An IFeatureWorkspace object can be passed if the parameter accepts a catalog path. An ITable or IStandAloneTable object can be used instead of a database file format (DBF) or geodatabase table. An ISpatialReference object can be passed if the data type of the parameter is Coordinate System.
A tool that updates an existing dataset, such as the Append tool, can have the output dataset defined using an ArcObjects component, such as IFeatureClass, because Append doesn't have an output dataset; the dataset it is updating is an input to the tool.
In the following code example, the Buffer tool takes an IFeatureClass object as input features. As the tool creates a new feature class, a catalog path must be used for output.
[C#]
public void IFeatureClassAsInput(IFeatureClass pFC, string buff_dist)
{
    // Create the geoprocessor.
    IGeoProcessor2 gp=new GeoProcessorClass();
    gp.OverwriteOutput=true;

    // Create variant array and populate with parameter values.
    IVariantArray parameters=new VarArrayClass();
    parameters.Add(pFC);
    parameters.Add(@"C:\temp\poitns_buff.shp");
    parameters.Add(buff_dist);

    // Execute the tool.
    gp.Execute("Buffer_analysis", parameters, null);
}
[VB.NET]
Public Sub IFeatureClassAsInput(ByVal pFC As IFeatureClass, ByVal dist As IGPLinearUnit)
    
    ' Create the geoprocessor.
    Dim gp As IGeoProcessor2=New GeoProcessor
    gp.OverwriteOutput=True
    
    ' Create variant array and populate with parameter values.
    Dim parameters As IVariantArray=New VarArray
    parameters.Add(pFC)
    parameters.Add("C:\temp\Lakes_buff.shp")
    parameters.Add(dist)
    
    ' Execute the tool.
    gp.Execute("Buffer_analysis", parameters, Nothing)
    
End Sub
The following code example shows a map document with an ILayer object joined to an ITable object. For the field parameters, you could pass IField objects instead of string field names.
[C#]
public void AddJoinWithILayerITable(string sMap, ITable pTable)
{
    IGeoProcessor2 gp=new GeoProcessorClass();
    IMapDocument pMapDoc=new MapDocumentClass();
    pMapDoc.Open(sMap, "");
    IMap pMap=pMapDoc.get_Map(0);
    ILayer pLayer=pMap.get_Layers(null, true).Next();
    IVariantArray parameters=new VarArrayClass();
    parameters.Add(pLayer);
    parameters.Add("BEAT"); // in_field
    parameters.Add(pTable);
    parameters.Add("BEAT"); // join_field
    gp.Execute("AddJoin_management", parameters, null);
}
[VB.NET]
Public Sub AddJoinWithILayerITable(ByVal sMap As String, ByVal pTable As ITable)
    
    Dim gp As IGeoProcessor2=New ESRI.ArcGIS.Geoprocessing.GeoProcessor()
    
    Dim pMapDoc As IMapDocument=New MapDocument
    pMapDoc.Open(sMap, "")
    
    Dim pMap As IMap=pMapDoc.Map(0)
    
    Dim pLayer As ILayer=pMap.Layers(Nothing, True).Next()
    
    Dim parameters As IVariantArray=New VarArray
    parameters.Add(pLayer)
    parameters.Add("BEAT")
    parameters.Add(pTable)
    parameters.Add("BEAT")
    
    gp.Execute("AddJoin_management", parameters, Nothing)
    
    ' The resulting join persists only for the current session.
    ' Use the CopyFeatures_management tool to save it on disk.
    
End Sub
Although a newly created output must be passed as a catalog path, a parameter expecting a workspace can be populated with an IWorkspace object. In the following code example, the Create Feature Dataset tool also accepts an ISpatialReference object as input:
[C#]
public void createFeatureDataset(IWorkspace workspace, ISpatialReference spatialRef)
{
    try
    {
        IVariantArray parameters=new VarArrayClass();
        parameters.Add(workspace);
        parameters.Add("Rivers");
        parameters.Add(spatialRef);
        gp.Execute("CreateFeatureDataset_management", parameters, null);
    }
    catch (Exception ex)
    {
        object sev=null;
        string msgs=gp.GetMessages(ref sev);
    }
}
[VB.NET]
Public Sub createFeatureDataset(ByVal workspace As IWorkspace, ByVal spatialRef As ISpatialReference)
    
    Try
    
    Dim parameters As IVariantArray=New VarArray
    parameters.Add(workspace)
    parameters.Add("Rivers")
    parameters.Add(spatialRef)
    
    gp.Execute("CreateFeatureDataset_management", parameters, Nothing)
    
    Catch ex As Exception
    
    Dim sev As Object=Nothing
    Dim msgs As String=gp.GetMessages(sev)
    
    End Try
    
End Sub

Using in_memory workspace

You can use in_memory workspace for intermediate tool outputs. Avoid using in_memory workspace for large datasets, as memory is always a limitation. See Using in_memory workspace for more information.
Some tools (for example, the Project tool) do not accept in_memory as output workspace. Check the tool's reference page to make sure the tool allows in_memory workspace.
[C#]
public void InMemoryWorkspaceTest(IArray points)
{
    IGeoProcessor2 gp=new GeoProcessorClass();

    IGPUtilities3 util=new GPUtilitiesClass();
    gp.OverwriteOutput=true;

    IVariantArray parameters=new VarArrayClass();
    parameters.Add("in_memory");
    parameters.Add("Parks");
    parameters.Add("POINT");
    parameters.Add(@"C:\gpqa\mytools\append\wells.gdb\well_1a");

    IGeoProcessorResult result=(IGeoProcessorResult)gp.Execute(
        "CreateFeatureclass_management", parameters, null);

    IGPValue gpVal=result.GetOutput(0);
    string inmemfc=gpVal.GetAsText();

    IFeatureClass pFC=util.OpenFeatureClassFromString(inmemfc);
    IFeatureBuffer buff=pFC.CreateFeatureBuffer();
    IFeatureCursor cur=pFC.Insert(true);

    object featureOID;
    ESRI.ArcGIS.Geometry.IPoint pt;
    for (int i=0; i < points.Count; i++)
    {
        pt=new ESRI.ArcGIS.Geometry.PointClass();
        pt=(Point)points.get_Element(i);
        buff.Shape=pt;
        featureOID=cur.InsertFeature(buff);
    }
    cur.Flush();

    parameters.RemoveAll();
    parameters.Add(result.GetOutput(0).GetAsText());
    parameters.Add(@"C:\sdk\data\testdata.gdb\in_mem_out");

    gp.Execute("CopyFeatures_management", parameters, null);
}
[VB.NET]
Public Sub InMemoryWorkspaceFeatures(ByVal points As IArray)
    
    Dim gp As IGeoProcessor2=New ESRI.ArcGIS.Geoprocessing.GeoProcessor()
    Dim util As IGPUtilities3=New GPUtilitiesClass()
    gp.OverwriteOutput=True
    
    Dim parameters As IVariantArray=New VarArray
    parameters.Add("in_memory")
    parameters.Add("Parks")
    parameters.Add("POINT")
    parameters.Add("C:\data\wells.gdb\wells")
    
    Dim result As IGeoProcessorResult2
    result=CType(gp.Execute("CreateFeatureClass_management", parameters, Nothing), IGeoProcessorResult2)
    
    Dim gpVal As IGPValue=result.GetOutput(0)
    Dim inmemfc As String=gpVal.GetAsText()
    
    Dim pFC As IFeatureClass=util.OpenFeatureClassFromString(inmemfc)
    Dim buff As IFeatureBuffer=pFC.CreateFeatureBuffer()
    Dim cur As IFeatureCursor=pFC.Insert(True)
    
    Dim featureOID As Object
    Dim pt As ESRI.ArcGIS.Geometry.IPoint
    For i As Integer=0 To points.Count - 1
        pt=New ESRI.ArcGIS.Geometry.Point()
        pt=CType(points.Element(i), ESRI.ArcGIS.Geometry.IPoint)
        buff.Shape=pt
        featureOID=cur.InsertFeature(buff)
    Next
    cur.Flush()
    
    parameters.RemoveAll()
    parameters.Add(result.GetOutput(0).GetAsText())
    parameters.Add("C:\data\output.gdb\in_mem_out")
    
    gp.Execute("CopyFeatures_management", parameters, Nothing)
    
End Sub

Using Feature Set and Record Set

Geoprocessing also provides Feature Set and Record Set data types to hold features and records in memory. The only use of Feature Set is to send features to a geoprocessing server. Using these types programmatically is complicated. A better option is to create an in_memory feature class using a geoprocessing tool such as Create Feature Class.
The following code example executes the BestPath service on bdhost ArcGIS Server in the gp/Routing. The service has one parameter of Feature Set type. It loads the incoming IFeatureClass object to a Feature Set and then passes it to the server tool. For more information, see An overview of geoprocessing with ArcGIS for Server.
[C#]
public void FeatureSetUsingServer(IFeatureClass pFC)
{
    IGeoProcessor2 gp=new GeoProcessorClass();

    gp.AddToolbox(@"http://bdhost/arcgis/services;gp/Routing");
    ITable table=(ITable)pFC;
    IRecordSetInit rsInit=new RecordSetClass();

    IQueryFilter2 qf=new QueryFilterClass();
    rsInit.SetSourceTable(table, qf); // Load fc.

    IRecordSet rs=rsInit as IRecordSet;
    IGPRecordSet gprs=new GPFeatureRecordSetLayerClass();

    gprs.RecordSet=rs;

    IVariantArray params=new VarArrayClass();
    parameters.Add(gprs);
    IGeoProcessorResult result;
    try
    {
        result=(IGeoProcessorResult)gp.Execute("BestPath", params, null);
        while (result.Status != esriJobStatus.esriJobSucceeded)
            System.Threading.Thread.Sleep(250);
        // Do next task with result.GetOutput(0).
    }
    catch (Exception ex)
    {
        object sev=null;
        string messages=gp.GetMessages(ref sev);
    }
}
[VB.NET]
Public Sub FeatureSetUsingServer(ByVal pFC As IFeatureClass)
    
    Dim gp As IGeoProcessor2=New ESRI.ArcGIS.Geoprocessing.GeoProcessor()
    
    gp.AddToolbox("http://bdhost/arcgis/services;gp/Routing")
    
    Dim table As ITable=CType(pFC, ITable)
    Dim rsInit As IRecordSetInit=New RecordSet()
    
    Dim qf As IQueryFilter2=New QueryFilter()
    rsInit.SetSourceTable(table, qf) ' Load fc into recordset.
    
    Dim rs As IRecordSet=CType(rsInit, IRecordSet)
    Dim gprs As IGPRecordSet=New GPFeatureRecordSetLayerClass()
    gprs.RecordSet=rs
    
    Dim parameters As IVariantArray=New VarArray()
    parameters.Add(gprs)
    Dim result As IGeoProcessorResult2
    Try
    result=CType(gp.Execute("BestPath", parameters, Nothing), IGeoProcessorResult2)
    While result.Status=esriJobStatus.esriJobExecuting
        Threading.Thread.Sleep(250)
    End While
    ' Other statements ...
    Catch ex As Exception
    Dim sev As Object=Nothing
    Dim messages As String=gp.GetMessages(sev)
    End Try
End Sub


See Also:

Using geoprocessing to develop applications
How to run a geoprocessing tool
Using in_memory workspace
How to work with geoprocessing services




To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):