About the Automate ArcGIS Desktop applications Sample
[C#]
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.esriSystem;
namespace DesktopAutomationCS
{
public partial class Form1 : Form
{
private IApplication m_application;
//Application removed event
private IAppROTEvents_Event m_appROTEvent;
private int m_appHWnd = 0;
//Retrieve the hWnd of the active popup/modal dialog of an owner window
[System.Runtime.InteropServices.DllImport("user32")]
private static extern int GetLastActivePopup(int hwndOwnder);
public Form1()
{
ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine);
InitializeComponent();
//Preselect option
cboApps.SelectedIndex = 0;
}
private void btnStartApp_Click(object sender, EventArgs e)
{
IDocument doc = null;
try
{
this.Cursor = Cursors.WaitCursor;
switch (cboApps.SelectedItem.ToString())
{
case "ArcMap":
doc = new ESRI.ArcGIS.ArcMapUI.MxDocumentClass();
break;
case "ArcScene":
doc = new ESRI.ArcGIS.ArcScene.SxDocumentClass();
break;
case "ArcGlobe":
doc = new ESRI.ArcGIS.ArcGlobe.GMxDocumentClass();
break;
}
}
catch { } //Fail if you haven't installed the target application
finally
{
this.Cursor = Cursors.Default;
}
if (doc != null)
{
//Advanced (AppROT event): Handle manual shutdown, comment out if not needed
m_appROTEvent = new AppROTClass();
m_appROTEvent.AppRemoved += new IAppROTEvents_AppRemovedEventHandler(m_appROTEvent_AppRemoved);
//Get a reference of the application and make it visible
m_application = doc.Parent;
m_application.Visible = true;
m_appHWnd = m_application.hWnd;
//Enable/disable controls accordingly
txtShapeFilePath.Enabled = true;
btnShutdown.Enabled = true;
btnDrive.Enabled = ShouldEnableAddLayer;
cboApps.Enabled = btnStartApp.Enabled = false;
}
else
{
m_appROTEvent = null;
m_application = null;
txtShapeFilePath.Enabled = false;
btnShutdown.Enabled = btnDrive.Enabled = false;
cboApps.Enabled = btnStartApp.Enabled = true;
}
}
private void btnShutdown_Click(object sender, EventArgs e)
{
if (m_application != null)
{
//Try to close any modal dialogs by sending the Escape key
//It doesn't handle the followings:
//- VBA is up and has a modal dialog
//- Modal dialog doesn't close with the Escape key
Microsoft.VisualBasic.Interaction.AppActivate(m_application.Caption);
int nestModalHwnd = 0;
while ((nestModalHwnd = GetLastActivePopup(m_application.hWnd)) != m_application.hWnd)
{
SendKeys.SendWait("{ESC}");
}
//Manage document dirty flag - abandon changes
IDocumentDirty2 docDirtyFlag = (IDocumentDirty2)m_application.Document;
docDirtyFlag.SetClean();
//Stop listening before exiting
m_appROTEvent.AppRemoved -= new IAppROTEvents_AppRemovedEventHandler(m_appROTEvent_AppRemoved);
m_appROTEvent = null;
//Exit
m_application.Shutdown();
m_application = null;
//Reset UI for next automation
txtShapeFilePath.Enabled = false;
btnShutdown.Enabled = btnDrive.Enabled = false;
cboApps.Enabled = btnStartApp.Enabled = true;
}
}
private void btnDrive_Click(object sender, EventArgs e)
{
this.Cursor = Cursors.WaitCursor;
try
{
IObjectFactory objFactory = m_application as IObjectFactory;
//Use reflection to get ClsID of ShapefileWorkspaceFactory
Type shpWkspFactType = typeof(ShapefileWorkspaceFactoryClass);
string typeClsID = shpWkspFactType.GUID.ToString("B");
string shapeFile = System.IO.Path.GetFileNameWithoutExtension(txtShapeFilePath.Text);
string fileFolder = System.IO.Path.GetDirectoryName(txtShapeFilePath.Text);
IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)objFactory.Create(typeClsID);
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile(fileFolder, 0); //(@"C:\data\test", 0);
//Create the layer
IFeatureLayer featureLayer = (IFeatureLayer)objFactory.Create("esriCarto.FeatureLayer");
featureLayer.FeatureClass = featureWorkspace.OpenFeatureClass(shapeFile); // ("worldgrid");
featureLayer.Name = featureLayer.FeatureClass.AliasName;
//Add the layer to document
IBasicDocument document = (IBasicDocument)m_application.Document;
document.AddLayer(featureLayer);
document.UpdateContents();
}
catch { } //Or make sure it is a valid shp file first
this.Cursor = Cursors.Default;
}
private void txtShapeFilePath_TextChanged(object sender, EventArgs e)
{
btnDrive.Enabled = ShouldEnableAddLayer;
}
private bool ShouldEnableAddLayer
{
get
{
//Only allow .shp file
if (System.IO.File.Exists(txtShapeFilePath.Text))
{
return (System.IO.Path.GetExtension(txtShapeFilePath.Text).ToLower() == ".shp");
}
else
{
return false;
}
}
}
#region "Handle the case when the application is shutdown by user manually"
void m_appROTEvent_AppRemoved(AppRef pApp)
{
//Application manually shuts down. Stop listening
if (pApp.hWnd == m_appHWnd) //compare by hwnd
{
m_appROTEvent.AppRemoved -= new IAppROTEvents_AppRemovedEventHandler(m_appROTEvent_AppRemoved);
m_appROTEvent = null;
m_application = null;
m_appHWnd = 0;
//Reset UI has to be in the form UI thread of this application,
//not the AppROT thread;
if (this.InvokeRequired) //i.e. not on the right thread
{
this.BeginInvoke(new IAppROTEvents_AppRemovedEventHandler(AppRemovedResetUI), pApp);
}
else
{
AppRemovedResetUI(pApp); //call directly
}
}
}
void AppRemovedResetUI(AppRef pApp)
{
txtShapeFilePath.Enabled = false;
btnShutdown.Enabled = btnDrive.Enabled = false;
cboApps.Enabled = btnStartApp.Enabled = true;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//Clean up
if (m_appROTEvent != null)
{
m_appROTEvent.AppRemoved -= new IAppROTEvents_AppRemovedEventHandler(m_appROTEvent_AppRemoved);
m_appROTEvent = null;
}
}
#endregion
}
}
[Visual Basic .NET]
Form1.vb
Imports ESRI.ArcGIS.Framework
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.DataSourcesFile
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.esriSystem
Public Class Form1
Private m_application As IApplication
'Application removed event
Private m_appHWnd As Integer = 0
Private m_appROTEvent As IAppROTEvents_Event
'Retrieve the hWnd of the active popup/modal dialog of an owner window
Declare Auto Function GetLastActivePopup Lib "user32" (ByVal hwndOwnder As Integer) As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Bind to Engine
ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine)
'Preselect option
cboApps.SelectedIndex = 0
End Sub
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
'Clean up
m_application = Nothing
m_appROTEvent = Nothing
End Sub
Private Sub btnStartApp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartApp.Click
Dim doc As IDocument = Nothing
Try
Me.Cursor = Cursors.WaitCursor
Select Case cboApps.SelectedItem.ToString()
Case "ArcMap"
doc = New ESRI.ArcGIS.ArcMapUI.MxDocumentClass()
Case "ArcScene"
doc = New ESRI.ArcGIS.ArcScene.SxDocumentClass()
Case "ArcGlobe"
doc = New ESRI.ArcGIS.ArcGlobe.GMxDocumentClass()
End Select
Catch
Finally
Me.Cursor = Cursors.Default
End Try
If doc IsNot Nothing Then
'Advanced (AppROT event): Handle manual shutdown, comment out if not needed
m_appROTEvent = New AppROTClass()
AddHandler m_appROTEvent.AppRemoved, AddressOf m_appROTEvent_AppRemoved
'Get a reference of the application and make it visible
m_application = doc.Parent
m_application.Visible = True
m_appHWnd = m_application.hWnd
'Enable/disable controls accordingly
txtShapeFilePath.Enabled = True
btnShutdown.Enabled = True
btnDrive.Enabled = ShouldEnableAddLayer
cboApps.Enabled = False
btnStartApp.Enabled = False
Else
m_appROTEvent = Nothing
m_application = Nothing
txtShapeFilePath.Enabled = False
btnShutdown.Enabled = False
btnDrive.Enabled = False
cboApps.Enabled = True
btnStartApp.Enabled = True
End If
End Sub
Private Sub txtShapeFilePath_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtShapeFilePath.TextChanged
btnDrive.Enabled = ShouldEnableAddLayer
End Sub
Private ReadOnly Property ShouldEnableAddLayer()
Get
If System.IO.File.Exists(txtShapeFilePath.Text) Then
Return System.IO.Path.GetExtension(txtShapeFilePath.Text).ToLower() = ".shp"
Else
Return False
End If
End Get
End Property
Private Sub btnDrive_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDrive.Click
Me.Cursor = Cursors.WaitCursor
Try
Dim objFactory As IObjectFactory = DirectCast(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 shapeFile As String = System.IO.Path.GetFileNameWithoutExtension(txtShapeFilePath.Text)
Dim fileFolder As String = System.IO.Path.GetDirectoryName(txtShapeFilePath.Text)
Dim workspaceFactory As IWorkspaceFactory = DirectCast(objFactory.Create(typeClsID), IWorkspaceFactory)
Dim featureWorkspace As IFeatureWorkspace = DirectCast(workspaceFactory.OpenFromFile(fileFolder, 0), IFeatureWorkspace)
'Create the layer
Dim featureLayer As IFeatureLayer = DirectCast(objFactory.Create("esriCarto.FeatureLayer"), IFeatureLayer)
featureLayer.FeatureClass = featureWorkspace.OpenFeatureClass(shapeFile)
featureLayer.Name = featureLayer.FeatureClass.AliasName
'Add the layer to document
Dim document As IBasicDocument = DirectCast(m_application.Document, IBasicDocument)
document.AddLayer(featureLayer)
document.UpdateContents()
Catch
End Try
Me.Cursor = Cursors.Default
End Sub
Private Sub btnShutdown_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShutdown.Click
If m_application IsNot Nothing Then
'Try to close any modal dialogs by sending the Escape key
'It doesn't handle the followings:
'- VBA is up and has a modal dialog
'- Modal dialog doesn't close with the Escape key
AppActivate(m_application.Caption)
Dim nestModalHwnd As Integer = GetLastActivePopup(m_application.hWnd)
Do Until nestModalHwnd = m_application.hWnd
SendKeys.SendWait("{ESC}")
nestModalHwnd = GetLastActivePopup(m_application.hWnd)
Loop
'Manage document dirty flag - abandon changes
Dim docDirtyFlag As IDocumentDirty2 = DirectCast(m_application.Document, IDocumentDirty2)
docDirtyFlag.SetClean()
'Exit
RemoveHandler m_appROTEvent.AppRemoved, AddressOf m_appROTEvent_AppRemoved
m_appROTEvent = Nothing
m_application.Shutdown()
m_application = Nothing
m_appHWnd = 0
'Reset UI for next automation
txtShapeFilePath.Enabled = False
btnShutdown.Enabled = False
btnDrive.Enabled = False
cboApps.Enabled = True
btnStartApp.Enabled = True
End If
End Sub
#Region "Handle the case when the application is shutdown by user manually"
Private Sub m_appROTEvent_AppRemoved(ByVal pApp As AppRef)
'Application is shut down manually. Stop listening
If pApp.hWnd = m_appHWnd Then 'compare by hwnd
RemoveHandler m_appROTEvent.AppRemoved, AddressOf m_appROTEvent_AppRemoved
m_appROTEvent = Nothing
m_application = Nothing
m_appHWnd = 0
'Reset UI has to be in the form UI thread of this application,
'not the AppROT thread;
If (Me.InvokeRequired) Then 'i.e. not on the right thread
Me.BeginInvoke(New IAppROTEvents_AppRemovedEventHandler(AddressOf AppRemovedResetUI), pApp)
Else
AppRemovedResetUI(pApp) 'call directly
End If
End If
End Sub
Private Sub AppRemovedResetUI(ByVal pApp As AppRef)
txtShapeFilePath.Enabled = False
btnShutdown.Enabled = False
btnDrive.Enabled = False
cboApps.Enabled = True
btnStartApp.Enabled = True
End Sub
#End Region
End Class