Skip to content
August 1, 2006 / Steven Pousty

Mr MXD – tell me all your datasources

UPDATE: Figured out a hack. Since this code is just to get rid of mundane work and not shippable – I am down with the hack. I updated the code below…
Been working on this problem where I wanted to know the name of all the datasets and their workspaces in a map document (mxd). We are getting ready to archive some data and we want to know which datasets are used in which MXDs. My first inclination was to open the MapDocument and ask it for it’s layers and it’s tables. But this seemed tedious and I found it hard to believe that the source tab in ArcMap did this. I dig around the object model and find out that MxDocument implements IDocumentDatasets whose only purpose in life is to hand back an enumeration of the datasets in your map document – BINGO! But for me the Java programmer I have no handle to the MxDocument class and it looks like you can only get this Class from a running ArcMap application (though I bet a Map Control in engine could give you this – but I don’t have engine).

So my path is clear – I need to automatically open ArcMap and then get it to work through the datasets and store that somewhere. I will skip the parts where I learned some of the nice features in the C# IO library and cut to the chase. I used the automation example (EDN gives a 404 for this sample) and modified it to do what I want. But not so fast. As per usual, some of the datasets have been moved and the map document doesn’t know where they are. If you right click on the dataset it knows what it wants to find, which is all I really need. I figure I will go ahead and crank it out.

Well my code works fine on everything but shapefiles which are missing. It works fine on FeatureClasses in a PGDB but not for shapefiles. Sorrow and despair overcomes me, but then I ping Brian and ask him what is going on! He suggest I use WorkspaceName rather than Workspace and lo and behold we are good to go.

Some comments before I show the code:

  1. Note to myself – I am going to try and use *Name objects more often, they seem more robust and they can always be used to open the full fledged object through the :: open method
  2. My app still throws this exception occaisionally : “A first chance exception of type ‘System.Runtime.InteropServices.COMException’ occurred in Automation.exe” – what does that mean?
  3. This process is slow since it basically fires up a new instance of ArcMap for each MXD document. This is one of those application you set running and then go get a Twix and a Diet Coke.

So here is the meat of the code that lists all the datasets in a list of map documents. Hope this helps….


private void cmdStartArcMap_Click(object sender, System.EventArgs e){
    if (folderBox.Text != null && folderBox.Text != ""){
        //Create a delegate instance and add it to AppRemoved event
        //ESRI code that I am not sure what it does
        m_pAppRot = new AppROTClass();
        m_appRemoved = new IAppROTEvents_AppRemovedEventHandler(AppRemoved);
        ((IAppROTEvents_Event)m_pAppRot).AppRemoved += m_appRemoved;

//Code written by SCP

List listOfMXDs = GetMXDs(folderBox.Text);
        StartArcMapProcessing(listOfMXDs);
    } else {
        MessageBox.Show("You need to enter a folder path before clicking Go");
    }
}

private List GetMXDs(String path){
    List results = new List(15);
    DirectoryInfo dir = new DirectoryInfo(path);

//get all the files ending in mxd in all the directories and add them to the List to return
    foreach (FileInfo f in dir.GetFiles("*.mxd", SearchOption.AllDirectories)) {
        String name = f.FullName;
        results.Add(name);

}
    return results;
}

private void StartArcMapProcessing(List listOfMXDs){
    if (listOfMXDs.Count > 0) {

foreach (String file in listOfMXDs) {
            try {
                Cursor.Current = Cursors.WaitCursor;
                System.Diagnostics.Debug.Print("Starting {0}",  file);
                //Start arcmap
                ArcMapDoc = new MxDocumentClass();
                //Get a reference to the application
                ArcMapApp = ArcMapDoc.Parent;
                //I don't think I need to Show arcmap
                ArcMapApp.Visible = false;
                ArcMapApp.OpenDocument(file);

//hack to wait for the doc to load in ArcMap. Since it is in a seperate thread 
                //there is not really a clean way to see if it's loaded or not
                Boolean docLoaded = false;
                while (!docLoaded) {
                    if (ArcMapDoc.Title != "Untitled") {
                        docLoaded = true;                                
                    }
                    Thread.Sleep(3000);
                }
ESRI.ArcGIS.Geodatabase.IEnumDataset datasets = ArcMapDoc.Datasets;
                ESRI.ArcGIS.Geodatabase.IDataset dataset = datasets.Next();
                while (dataset != null) {

ESRI.ArcGIS.esriSystem.IName name = dataset.FullName;
                    ESRI.ArcGIS.Geodatabase.IDatasetName dsname = name as ESRI.ArcGIS.Geodatabase.IDatasetName;
                    ESRI.ArcGIS.Geodatabase.IWorkspaceName wsname = dsname.WorkspaceName;

String[] row = { file, wsname.PathName, dsname.Name };
                    resultGridView.Rows.Add(row);
                    dataset = datasets.Next();
                }

QuitArcMap();
            }catch (Exception) {
                System.Diagnostics.Debug.Print("exception");
                QuitArcMap();
            }

}

}
    else {
        MessageBox.Show("There were no MXDs found in the directory you specified");
    }
    //disable and enable buttons
    cmdStartArcMap.Enabled = false;
    cmdStartArcMap.Text = "Finished";
    Cursor.Current = Cursors.Default;
}

private void QuitArcMap(){
    if (ArcMapDoc != null)
    {
        ArcMapDoc.SetClean();
        ArcMapApp.Shutdown(); //Quit ArcMap
        ArcMapDoc = null;     //Release m_pDoc
        ArcMapApp = null;     //Release m_pApp
        cmdStartArcMap.Enabled = true;

}
}

7 Comments

Leave a Comment
  1. brian goldin / Aug 1 2006 10:36 pm

    Hey steve great post. I’m suprised at how little content you see on arcobjects.

    Name objects are sweet. think of them as lightweight monikers to the real deal. these can get generated by the workspace to be passed around your app without having to open the real object which can sometimes be expensive in both memory and resources. this is why you were able to get the workspace out of a datasource when the the actual workspace doesn’t even exist (had probably been deleted). you were working with the pointer to it – if you tried to actually open it you’d get smacked down.

    thanks for the 404 – i’ll see what we can do.

  2. brian goldin / Aug 1 2006 10:37 pm

    PS – we miss you around here…

  3. GeoMullah / Aug 2 2006 9:42 am

    Great post. Even though I don’t work with that stuff too much anymore, it was a really good post that I can point others to. Your new bosses should give you a raise.

  4. GeoMullah / Aug 2 2006 10:02 am

    Also. . . Steve’s bosses should send him to the UC next week.

  5. raf / Nov 12 2007 8:20 am

    Hello,

    I’m a novice using java language, but it’s a great code though. When i make a new program with the code pasted in jcreator. I get an error at ” catch” with message … catch(Exception)

    Can anybody help me or can this code be ran from arcmap?

    Thanks in advance

    Raf

  6. Steven Citron-Pousty / Nov 12 2007 8:35 am

    Raf:
    Sorry I wasn’t clear, but this is C# code, not Java.
    Steve

  7. raf / Nov 13 2007 2:43 am

    Thanks Steve,

    So if I run the code from Microsoft Visual c#.NET, it should work?

    The fact is , i’m a GIS analyst, not a daily programmer, but our service had the problem with the mxd listing of datasources for quite a while know.

    I’m going to give it a try … thanks in advance.

    Raf

Leave a reply to brian goldin Cancel reply