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