Automating ArcGIS for Desktop applications


Summary
This topic explains how to automate ArcGIS for Desktop applications by creating a stand-alone application that drives ArcMap, ArcScene, or ArcGlobe remotely from a separate process space.


About automating ArcGIS for Desktop applications

To automate an ArcGIS for Desktop application, follow these steps:
  1. Start the ArcGIS for Desktop application.
    1. Create the driving application from a stand-alone application project (for example, a Windows application project).
    2. Create an instance of the document object of your target application. See the following table:
      Application
      Document type
      ArcMap
      ArcGlobe
      ArcScene
    1. Once the document is instantiated, get an IApplication reference to the application object via IDocument.Parent.
The following code shows how to start ArcMap when a button on a form is clicked (add reference to ESRI.ArcGIS.Framework and ESRI.ArcGIS.ArcMapUI assemblies):
[C#]
private ESRI.ArcGIS.Framework.IApplication m_application;

private void btnStartApp_Click(object sender, EventArgs e)
{
    ESRI.ArcGIS.Framework.IDocument doc = new ESRI.ArcGIS.ArcMapUI.MxDocumentClass();
    m_application = doc.Parent;
    m_application.Visible = true;
}
[VB.NET]
Private m_application As ESRI.ArcGIS.Framework.IApplication

Private Sub btnStartApp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartApp.Click
    Dim doc As ESRI.ArcGIS.Framework.IDocument = New ESRI.ArcGIS.ArcMapUI.MxDocumentClass()
    m_application = doc.Parent
    m_application.Visible = True
End Sub
  1. Interact with the application and create components
    1. Cast the application object to the IObjectFactory interface.
      • Accessing components—Components can be accessed from the application object reference.
      • Creating components—In .NET, when you use the C# or VB.NET operator, it creates the object in the driving application's process space, not in the target application (for example, ArcMap) process. Often, what you really want is to create an object in the target application process space while accessing control of it from the driving application. This sort of control is made possible by the IObjectFactory interface, obtainable from the application object.
    2. Determine the identifier (ProgID or CLSID) of the component to be created; for example, the FeatureLayerClass type has a ProgID of esriCarto.FeatureLayer. The ProgID is different than the .NET type name of the class. You can use .NET reflection to get the CLSID by calling Type.Guid.
    3. Call IObjectFactory.Create to create the object.
The following code shows how to add a layer from a shapefile to the running application (add reference to ESRI.ArcGIS.Framework, ESRI.ArcGIS.ArcMapUI, ESRI.ArcGIS.Carto, ESRI.ArcGIS.Geometry, ESRI.ArcGIS.Geodatabase, and ESRI.ArcGIS.DataSourcesFile assemblies):
[C#]
IObjectFactory objFactory = m_application as IObjectFactory;

//Use reflection to get ClsID of ShapefileWorkspaceFactory.
Type shpWkspFactType = typeof(ShapefileWorkspaceFactoryClass);
string typeClsID = shpWkspFactType.GUID.ToString("B");

IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)objFactory.Create(typeClsID);
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)
    workspaceFactory.OpenFromFile(@"C:\data\test", 0);

//Create the layer.
IFeatureLayer featureLayer = (IFeatureLayer)objFactory.Create(
    "esriCarto.FeatureLayer");
featureLayer.FeatureClass = featureWorkspace.OpenFeatureClass("worldgrid");
featureLayer.Name = featureLayer.FeatureClass.AliasName;

//Add the layer to the document.
IBasicDocument document = (IBasicDocument)m_application.Document;
document.AddLayer(featureLayer);
document.UpdateContents();
[VB.NET]
Dim objFactory As IObjectFactory = TryCast(m_application, IObjectFactory)

'Use reflection to get ClsID of ShapefileWorkspaceFactory.
Dim shpWkspFactType As Type = GetType(ShapefileWorkspaceFactoryClass)
Dim typeClsID As String = shpWkspFactType.GUID.ToString("B")

Dim workspaceFactory As IWorkspaceFactory = DirectCast(objFactory.Create(typeClsID), IWorkspaceFactory)
Dim featureWorkspace As IFeatureWorkspace = DirectCast(workspaceFactory.OpenFromFile("C:\data\test", 0), IFeatureWorkspace)

'Create the layer.
Dim featureLayer As IFeatureLayer = DirectCast(objFactory.Create("esriCarto.FeatureLayer"), IFeatureLayer)
featureLayer.FeatureClass = featureWorkspace.OpenFeatureClass("worldgrid")
featureLayer.Name = featureLayer.FeatureClass.AliasName

'Add the layer to the document.
Dim document As IBasicDocument = DirectCast(m_application.Document, IBasicDocument)
document.AddLayer(featureLayer)
document.UpdateContents()
  1. Shut down the application after proper clean up.
    1. Handle any modal dialog boxes currently displayed in the application.
    2. To avoid the Save dialog box that opens when the application exits, call either IApplication.SaveDocument (to save changes) or IDocumentDirty2.SetClean (to abandon changes).
    3. Call IApplication.Shutdown to exit the application.
The following code cleans up and exits the application (add reference to ESRI.ArcGIS.Framework assembly):
[C#]
//Manage document dirty flag; abandon changes.
IDocumentDirty2 docDirtyFlag = (IDocumentDirty2)m_application.Document;
docDirtyFlag.SetClean();

//Exit.
m_application.Shutdown();
[VB.NET]
'Manage document dirty flag; abandon changes.
Dim docDirtyFlag As IDocumentDirty2 = DirectCast(m_application.Document, IDocumentDirty2)
docDirtyFlag.SetClean()

'Exit.
m_application.Shutdown()

Notes on automation

Normally, ArcGIS for Desktop applications are extended by user customizations made available to the application through component categories. These custom objects exist in the ArcGIS for Desktop application process space; access between them is direct and fast since they do not need to communicate between each other across process boundaries. This is generally referred to as in-process or in-proc.
Conversely, automation is possible by creating a stand-alone application that obtains a reference to, and works with, the ArcGIS for Desktop application remotely from its separate process space. In this case, there are two separate applications running and, consequently, two separate process spaces. Although as far as the client is concerned, things appear to be the same in automation as they are in the in-proc case; the following are important differences of which programmers need to be aware:
  • Performance—Interapplication communication (whether through a component object model [COM] or some other mechanism) must cross process boundaries since all applications live in their own protected address space. When a COM object is created in one process and accessed in another, interprocess marshaling (communication) must occur (this is very expensive). In an application, such as ArcMap, where large numbers of components are accessed over short periods of time (such as in drawing or query), this overhead can become extreme.
  • Process confined types—Certain types (such as a graphical device interface [GDI] handles and others) cannot be used within the context of a different process from which they were created or are restricted in what can be done with them in that foreign process. For instance, a bitmap created in one process and handed to another through COM (for example, as an OLE_HANDLE) cannot be rendered on a device context (DC) in the foreign process space.
  • Deadlocks and other threading issues—Some areas of ArcGIS do not currently support access from a foreign process space. Many of these limitations are due to constraints of the types of system objects that can be shared between separate process spaces (some constraints are due to performance issues).


See Also:

Sample: Automate ArcGIS for Desktop applications




Development licensing Deployment licensing
ArcGIS for Desktop Basic ArcGIS for Desktop Basic
ArcGIS for Desktop Standard ArcGIS for Desktop Standard
ArcGIS for Desktop Advanced ArcGIS for Desktop Advanced