Select to view content in your preferred language

Need to Replace Out of Date Map Services in MXDs

2301
23
10-09-2013 02:58 PM
RandyKreuziger
Frequent Contributor
We just upgraded ArcGIS Server from 10.0 to 10.1.  Several users have MXDs that contain a map service that retired during the upgrade.  With the map service gone those MXDs take 10 to 30 minutes to open and another 5 minutes just to right click on the service in the TOC so it can be removed.

What is there in ArcPy to find and replace map services?  Let me know if this topic should go in another forum.

And, why the heck does ArcGIS Desktop spend so much time looking for a map service before giving up?
Tags (2)
0 Kudos
23 Replies
MattSayler
Frequent Contributor
Looks like layer objects contain information for services in 'serviceProperties' but it's a read-only attribute. You'll probably have to setup the script to use AddLayer(), RemoveLayer(), etc. instead of findAndReplaceWorkspacePath()/replaceDataSource().

Edit: Actually looking a little deeper at AddLayer(), I'm not 100% sure if that will work, as it takes a path to a layer file. Is it possible to save a layer file for a service?
0 Kudos
RandyKreuziger
Frequent Contributor
Thanks Matt, RemoveLayer will work.  I've just got one last problem.  Since I'm running this script for other users I don't want to remove all layers with broken datasources.  A user may have data on their C: drive or a protected network folder, but since I'm running the script those layers show up as broken.

.The only thing I want to remove are broken map services.  Unfortunately, I haven't been able to find just map services.
The line with lyr.supports("SERVICEPROPERTIES") errors off if the broken layer is a table view since TableViews don't have the SUPPORTS attribute.  Any ideas.


i
mport arcpy

fileName = "DBS100"
myMXD = "H:/_maps/" + fileName + ".mxd"
print myMXD
mxd = arcpy.mapping.MapDocument(myMXD)
for df in arcpy.mapping.ListDataFrames(mxd):
    for lyr in arcpy.mapping.ListBrokenDataSources(mxd):
        print "  Broken DataSource: " + lyr.name
        # TableViews are erroring off because that object has no supports attribute .
        if lyr.supports("SERVICEPROPERTIES"):
            if lyr.serviceProperties['ServiceType'] == "MapServer":
                print lyr.serviceProperties

del mxd
0 Kudos
MichaelVolz
Esteemed Contributor
This is definitely going to be a problem.  Is there anyway you can restore the old mapservices again, so you can run a python script to remove and/or replace these mapservices?  Can you have both versions of ArcGIS Server running at the same time or did you upgrade in place?  This would be a reason why you would want to build new servers when you upgrade your ArcGIS Server environment.
0 Kudos
MattSayler
Frequent Contributor
Thanks Matt, RemoveLayer will work.  I've just got one last problem.  Since I'm running this script for other users I don't want to remove all layers with broken datasources.  A user may have data on their C: drive or a protected network folder, but since I'm running the script those layers show up as broken.

.The only thing I want to remove are broken map services.  Unfortunately, I haven't been able to find just map services.
The line with lyr.supports("SERVICEPROPERTIES") errors off if the broken layer is a table view since TableViews don't have the SUPPORTS attribute.  Any ideas.


i
mport arcpy

fileName = "DBS100"
myMXD = "H:/_maps/" + fileName + ".mxd"
print myMXD
mxd = arcpy.mapping.MapDocument(myMXD)
for df in arcpy.mapping.ListDataFrames(mxd):
    for lyr in arcpy.mapping.ListBrokenDataSources(mxd):
        print "  Broken DataSource: " + lyr.name
        # TableViews are erroring off because that object has no supports attribute .
        if lyr.supports("SERVICEPROPERTIES"):
            if lyr.serviceProperties['ServiceType'] == "MapServer":
                print lyr.serviceProperties

del mxd

You could use ListLayers() instead of ListBrokenDataSources(), and just look for layers that have service properties that match the old service. It might work out better to make all your checks fairly explicit since there are a variety of situations you have to work with.

This is definitely going to be a problem.  Is there anyway you can restore the old mapservices again, so you can run a python script to remove and/or replace these mapservices?  Can you have both versions of ArcGIS Server running at the same time or did you upgrade in place?  This would be a reason why you would want to build new servers when you upgrade your ArcGIS Server environment.

I don't think you can replace the source for services like you can for layers because it's not just a file path. You have to update the server, service name, etc. which are read-only. Using arcpy to remove and add the services as layers is the only way to automate this right now as far as I can tell. I'm not 100% sure, but that's what it has looked like from the research I've done.
0 Kudos
MichaelVolz
Esteemed Contributor
Matt:

You are probably right about not being able to replace the datasource.  I would try to use the UpdateLayer method, but this might not be possible because the source might already be broken. You would need to know what the starting layer is so you know what layer to replace it with if you have multiple mapservices to choose from.  This would be important if you had many mapservices that were retired at once and replaced with newer mapservices.

The UpdateLayer method is how I converted raster images sourced from SDE with raster mosaic datasets sourced from a mapped network location.
0 Kudos
MattSayler
Frequent Contributor
Oh, that's a good idea. UpdateLayer uses an existing lyr file, same as AddLayer, correct? I told Randy to use AddLayer and RemoveLayer, but I bet that would shortcut things a little. I was thinking that wouldn't work because of the Read-Only attributes, but it probably just does a remove and an add under the hood.

Can a lyr file be saved for a service though? That's the biggest question in my mind.
0 Kudos
MichaelVolz
Esteemed Contributor
I would think you could create a lyr file from a service as my organization has a few lyr files like this.  I believe the only problem with this method is if the mapservice exists in a group layer as you need to know the index of the layer inside the group layer if you want it to maintain its visibility with respect to the other layers in the group layer.  This might not be the case, so it would need to be tested.
0 Kudos
RandyKreuziger
Frequent Contributor
It finally came to me.  Putting the supports("SERVICEPROPERTIES") inside a try except was the missing piece.  Now I should be able to remove all broken map services without it failing when the broken layer is a TableView.  See the code below.

New question.  Is there a way in 10.1 to determine the MXD version?  I'd like to run this script on 10.1 but save out MXD in the same version as the original.


mxd = arcpy.mapping.MapDocument(myMXD)
for df in arcpy.mapping.ListDataFrames(mxd):
    print "*** New Data Frame"
    print "    Listing Data Frame Layers"
    for lyr in arcpy.mapping.ListBrokenDataSources(mxd):        
        print "  Broken DataSource: " + lyr.name
        # TableViews are erroring off because that object has no attribute supports.
        try:
            if lyr.supports("SERVICEPROPERTIES"):
                if lyr.serviceProperties['ServiceType'] == "MapServer":
                    print "MapServer"
                    print lyr.serviceProperties
        except:
            print "Layer has no SUPPORTS attribute: " + lyr.name
0 Kudos
MattSayler
Frequent Contributor
Not seeing it in the map document properties directly. Kind of strange since you can select a version using the 'saveACopy' method. 'Describe()' will only return the type ("MapDocument").

Only other way I can think of is to test for properties that are unique to different versions. Looks like there are some candidates between 10.0 and 10.1 at least:
http://resources.arcgis.com/en/help/main/10.1/#/MapDocument/00s30000000n000000/
http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/MapDocument/00s30000000n000000/

for example:
if mxd.activeDataFrame:
    print "Version 10.1"


Not sure how bulletproof that methodology will be though.
0 Kudos