Which data format to choose to avoid file lock restriction

2672
11
05-09-2012 07:35 AM
Occasional Contributor II
I am working on a standalone application (C# VS 2010 arcGIS Engine 10) continuously running on a single computer. (this application should never stop).
part of it is a simple Map Document manager with MapControl+TOCControl : so user should be able to open MXD document, change few things like layer symbology, transparency, map name, and Save the map.
My map document and data files has to be stored this way : 1 folder for each Map Document containing 1 MXD file and all associated data files (vector data).

So each time the user open a map document (IMapDocument.Open), lock files are created, and as the application never stop, these lock files are not (never) removed, even if the user close the map and open another one. (or maybe I do something wrong there in my code).

My issue is that the user should be able to Delete a Map according this process : delete the folder containing the map document and all content : the mxd file and all data files (like shapefile). But once the map document has been opened, there are always lock files there and full delete of my folder is not possible.

Shapefile, file geodatabase and personal geodatabase generate LOCK files, so what kind of data format could I use ?

the important point is that my application does not allow data editing, I am only developing functionnalities for map configuration (symbols, zoom scale) and drawing temporary geometry in graphic layers... so I really don't need these LOCK files. I just need to use my vector data as basemap !
So I guess, I definitly need a read-only data format...

I've tried base map layer which is not working because it's a group layer still loading data such as shapefile of feature class
I've tried SDC data which is working fine, but i don't think I can generate my own SDC files with ArcGIS Desktop (is it possible ?)

any solution ?
Reply
0 Kudos
11 Replies
Occasional Contributor
I am working on a standalone application (C# VS 2010 arcGIS Engine 10) continuously running on a single computer. (this application should never stop).
part of it is a simple Map Document manager with MapControl+TOCControl : so user should be able to open MXD document, change few things like layer symbology, transparency, map name, and Save the map.
My map document and data files has to be stored this way : 1 folder for each Map Document containing 1 MXD file and all associated data files (vector data).

So each time the user open a map document (IMapDocument.Open), lock files are created, and as the application never stop, these lock files are not (never) removed, even if the user close the map and open another one. (or maybe I do something wrong there in my code).

My issue is that the user should be able to Delete a Map according this process : delete the folder containing the map document and all content : the mxd file and all data files (like shapefile). But once the map document has been opened, there are always lock files there and full delete of my folder is not possible.

Shapefile, file geodatabase and personal geodatabase generate LOCK files, so what kind of data format could I use ?

the important point is that my application does not allow data editing, I am only developing functionnalities for map configuration (symbols, zoom scale) and drawing temporary geometry in graphic layers... so I really don't need these LOCK files. I just need to use my vector data as basemap !
So I guess, I definitly need a read-only data format...

I've tried base map layer which is not working because it's a group layer still loading data such as shapefile of feature class
I've tried SDC data which is working fine, but i don't think I can generate my own SDC files with ArcGIS Desktop (is it possible ?)

any solution ?


Hello,

If you are closing the map document, the locks (lock files) would be removed.  Are you closing the map document with IMapDocument::Close?

Since it is your intention to delete the map document and associated feature classes (shapefiles, geodatabase feature classes, etc.), I wonder if first removing the feature layers from the map will remove the lock files.  A call to IDataLayer2.Disconnect() on a FeatureLayer object should disconnect the source data from the layer.  I would follow that call with IMap.DeleteLayer().  This may help if closing the map document with IMapDocument.Close() does not remove the locks, although I think it should.


Also, on a different approach, I think you can delete lingering lock files so if you explicitly delete (programmatically) the files in the folder first, you can then delete the folder.  I am quite sure I saw this workaround once to lingering lock files.  But you shouldn't be seeing lingering lock files in the first place if an application is no longer browsing for the file or referencing it on a map.
Reply
0 Kudos
Occasional Contributor II
thanks for the tips, I would try to remove layers first to see if lock files are deleted (and post the result asap)

however, i am wondering how to close properly a map previoulsy opened on my MapControl by following code :

IMapControl3 m_mapControl3 = (IMapControl3)axMapControl.Object;
m_mapControl3.LoadMxFile(myFileName, string.Empty);


I don't see an "unloadMxFile" ! and when I use LoadMxFile to open another Map Document, the previous one still have lock files...
How can i close properly with IMapDocument::Close in my case ?
Reply
0 Kudos
Regular Contributor II
In the initial post you mentioned you used IMapDocument.Open.  On the same interface there is a close method.  If you LoadMxFile, my understanding is you are loading one of the maps on the document but not the document itself.  If so I would not be surprised if the next call to load document does not release the first map document correctly.  If you keep an variable that references the map control's map, load a new map then use the comreleaser release on the variable referencing the first map, do you get any different result?
Reply
0 Kudos
Occasional Contributor
thanks for the tips, I would try to remove layers first to see if lock files are deleted (and post the result asap)

however, i am wondering how to close properly a map previoulsy opened on my MapControl by following code :

IMapControl3 m_mapControl3 = (IMapControl3)axMapControl.Object;
m_mapControl3.LoadMxFile(myFileName, string.Empty);


I don't see an "unloadMxFile" ! and when I use LoadMxFile to open another Map Document, the previous one still have lock files...
How can i close properly with IMapDocument::Close in my case ?


Well if you are using IMapControl3, that is more equivalent to IMap than to IMapDocument.  IMapControl/IMapControl3 seem to be shortcuts to IMap when working with a MapControl.  So you did not open a map document with IMapDocument.Open() but rather you associated your mapControl with a given map using IMapControl.LoadMxFile, would you agree?

I think agray1 is on the right track, however, I am not sure you have an object variable that is referencing the first map.  You only have the module-level variable m_mapControl3, but I would not comrelease that object because it is a class-level or module-level variable.  Do you have any variables that may be referencing the first map, like an IMap type object?  And can you confirm whether you did or did not use IMapDocument.Open().  Right now I cannot picture why you would use IMapDocument.Open() since you would not use an IMapDocument type object as an argument to IMapControl.LoadMxFile because LoadMxFile just takes 2 string values as arguments.  IMapDocument is more for reading and writing a map document, which you may very well be doing in your application but as a separate workflow.

Well, if you do indeed use IMapDocument.Open(), make sure you call IMapDocument.Close() when you are done so that any layers in that map document loose their lock files.  As for the trickier IMapControl3 type object you have that is module-level, I do not think you can dispose of that object and it may very well be holding on to the map layers when you load a different map file.  That could be a bug if you cannot comrelease your m_mapControl3 object.
Reply
0 Kudos
Regular Contributor II
Good point Edgar,  I would definitely not release the mapcontrol.   However the mapcontrol has a map property which is read and pass by ref.  You could declare an IMap variable assign the mapcontrol.map property, load a new map (LoadMxFile), and com release the variable that (hopefully) still points to the original map.  Its' all a kludgy mess at this point anyway but such is my experience with lock files...

Another thing to consider when deleting files accessed by AO, is AO has delete methods such as IDataset.Delete and others.  They will usually work even with lock files if the lock files are owned by the process calling the delete method.  I have found this much more reliable because of lock files than calls to .net file system methods for deleting files and folders.
Reply
0 Kudos
Occasional Contributor II
Thanks to both of you for contribution,

My code was a little bit confusing as I was loading a map in MapControl by LoadMxFile(), and then trying to close using IMapDocument::Close.
So I change my code to use IMapDocument to Open and Close. My MXD Doucment only contains 1 DataFrame with 1 Shapefile Layer.
When I open the document, I display the map in my MapControl, and I'm still not sure I am doing it right, as the lock file is not removed once I close my doc.


    // private members
    private IMapDocument m_mapDoc;
    private IMap m_map;           
   
    ...

    // Function Open a Map :
    if (axMapControl.CheckMxFile(mxdFileName))
    {
        // If a map was already opened
        if (m_mapDoc != null)
        {
            // Close the map
            m_mapDoc.Close();
            Marshal.ReleaseComObject(m_map);
            Marshal.ReleaseComObject(m_mapDoc);
        }
        else
        {
            m_mapDoc = new MapDocumentClass();
        }

        m_mapDoc.Open(mxdFileName);
        m_map = m_mapDoc.get_Map(0);
        axMapControl.Map = m_map;
    }

    ...

    // Function Close a Map :
    if (m_mapDoc != null)
    {
        // Close the map (and stop displaying the map on MapControl)
        m_mapDoc.Close();
        Marshal.ReleaseComObject(m_map);
        Marshal.ReleaseComObject(m_mapDoc);
    }


i've tried a simple test : my application run with the main Form. From there, a button open with ShowDialog() my Map Form (which contain my MapControl axMapControl) : on this Form_Load, I open my MXD doc -> lock file is created for the shapefile, then on Form_Closing, I close my MXD Doc -> the lock file is not removed ! So it seems that MapControl still hold something from the map... any ideas ? I tried the ReleaseCom, but don't know exactly how to ComRelease properly.

other issue : to delete my files, including lock files, i will test your solutions asap (IDataLayer2.Disconnect, IMap.DeleteLayer, ComReleaser), but would definitly need help for using ComReleaser in c# .net 3.5 arcgi engine 10.0.
Reply
0 Kudos
Occasional Contributor II
I'm trying to delete my Map Folder properly, in case there are lock files in it, but does not find the way... (I don't even deal with MapControl there)
For 1 folder, I have 1 mxd file with 1 layer (shapefile)

The following code get an error on _dataLayer2.Disconnect() :


                string _myFolder = @"D:\AllMyMaps\Map1";        //for example
                if (Directory.Exists(_myFolder) == true)
                {
                    string _mxdFileName = @"D:\AllMyMaps\Map1\Map1.mxd";       // for example

                    if (File.Exists(_mxdFileName ) == true)
                    {
                        _mapDoc.Open(_mxdFileName );

                        IMap _map = _mapDoc.get_Map(0);       // I get only 1 map with only 1 shapefile
                        ILayer _layer = _map.get_Layer(0);

                        FeatureLayer _featureLayer = new FeatureLayerClass();
                        _featureLayer = (FeatureLayer)_layer;

                        IDataLayer2 _datalayer2 = (IDataLayer2)_featureLayer;
                        _datalayer2.Disconnect();

                        _map.DeleteLayer(_layer);

                        _mapDoc.Save(true, false);

                        Marshal.ReleaseComObject(_datalayer2);
                        Marshal.ReleaseComObject(_featureLayer);
                        Marshal.ReleaseComObject(_map);

                        _mapDoc.Close();
                        Marshal.ReleaseComObject(_mapDoc);
                    }

                    // Delete the folder by System.IO
                    Directory.Delete(myFolder, true);
             }


Exception is : [System.Runtime.InteropServices.COMException]  {"Error HRESULT E_FAIL has been returned from a call to a COM component."}
Reply
0 Kudos
Occasional Contributor II
Ok I got something working to delete properly in one case : Map Document with Shapefiles.
I open my map, then delete all shpaefiles layers, removing them from my map, close the map and then release all arcobjects Objects !


        if (Directory.Exists(repertoire) == true)
                {
                    string _cheminFichierMXD = @"D:\myMaps\MyMap1\MyMap1.mxd";

                    if (File.Exists(_cheminFichierMXD) == true)
                    {
                        _mapDoc.Open(_cheminFichierMXD);

                        IMap _map = null;            // initialize object to "null" in order to be able to comrelease at the end
                        ILayer _layer = null;
                        FeatureLayer _featureLayer = null;
                        IDataset _dataset = null;

                        int _mapsCount = _mapDoc.MapCount;
                        for (int ixMap = 0; ixMap < _mapsCount; ixMap++)
                        {
                            _map = _mapDoc.get_Map(ixMap);

                            int _layersCount = _map.LayerCount;
                            for (int ixLayer = (_layersCount-1); ixLayer > -1; ixLayer--)
                            {
                                _layer = _map.get_Layer(ixLayer);
                                _featureLayer = _layer as FeatureLayer;
                                if (_featureLayer != null)
                                {
                                    if (_featureLayer.FeatureClass != null)
                                    {
                                        _dataset = _featureLayer.FeatureClass as IDataset;
                                        if (_dataset != null)
                                        {
                                            if (_dataset.CanDelete())
                                            {
                                                _dataset.Delete();     // shapefiles are deleted there
                                            }
                                        }
                                    }
                                }

                                _map.DeleteLayer(_layer);
                            }
                        }

                        _mapDoc.Save(true, false);
                        _mapDoc.Close();

                        Marshal.FinalReleaseComObject(_dataset);
                        Marshal.FinalReleaseComObject(_featureLayer);
                        Marshal.FinalReleaseComObject(_map);
                        Marshal.FinalReleaseComObject(_mapDoc);       // lock files disappeared at this point
                    }

                    // Suppression complète du répertoire
                    Directory.Delete(repertoire, true);      // work without error, as there is no lock files !
                }


but this code doesn't work with File Geodatabase, as lock files are still there... i'll try the Disconnect() in this case.

Am I on the right track ? (I would like to manage at least Shpaefiles, File & personal Geodatabase)
Reply
0 Kudos
Occasional Contributor
I will try to see if I reproduce the exception with the Disconnect method today based on your details and code.  Which service pack do you have for ArcGIS Engine Runtime 10.0?  SP4?
Reply
0 Kudos