Subscribe Now: Feed Icon

Sunday, December 18, 2011

MSD tools: Changing Connection and Publishing

Last month I got a new assignment to develop a tool that changes the layers’ connection in a MXD file and publish it in ArcGis Server. It is fairly easy to do it using ArcMap but we have too many environments/servers and whatever we can automate should be automated.

Since then the team went to a Systematics Event (ESRI local provider) where they talked about the new stuff in version 10.1, namely that publishing will only support MSD files (not MXD files) – so the task got changed a bit. For more information on MSD functionality and Performance considerations.

Finding how to change the connection of the layers was easy enough with the IMSDHelper interface:

  1. private const bool UseRelativePath = true;
  2. private const bool ValidateLayerConnection = false;
  4. /// <summary>
  5. /// Changes the SDE connection string for all the layers in the MSD file
  6. /// </summary>
  7. /// <param name="msdFilePath"></param>
  8. /// <param name="connectionString"></param>
  9. /// <param name="resultMsdFile">result file is relative path</param>
  10. public static void ChangeConnection(string msdFilePath, string connectionString, string resultMsdFile)
  11. {
  12.     IMSDHelper helper = new MSDHelper();
  13.     helper.Open(msdFilePath);
  14.     var maps = helper.GetMaps();
  15.     for (var i = 0; i < maps.Count; i++)
  16.     {
  17.         var layers = helper.GetLayers(maps.Element[i]);
  18.         for (var j = 0; j < layers.Count; j++)
  19.         {
  20.             helper.PutWorkspaceConnectionStringInLayer(layers.Element[j], connectionString, ValidateLayerConnection);
  21.         }
  22.     }
  23.     helper.SaveAs(resultMsdFile, UseRelativePath);
  24. }

We simply iterate through all the maps and all the inner layers and change the connection to the given one.


But what about Publishing the MSD automatically? This proved to be a bit more problematic. It was fairly easy to find a Python script using arcPy that publishes MSD files. But less so on ArcObjects code, in the end I found this forum post which led me to this code (just run it through Google Translate since it’s in Chinese). The code looks like this:

  1. public static void PublishToServer(string mapFilePath, string serverName, string serviceName)
  2. {
  3.     IGISServerConnection gisServerConnection = new GISServerConnectionClass();
  4.     gisServerConnection.Connect(serverName);
  5.     var serverObjectAdmin = gisServerConnection.ServerObjectAdmin;
  6.     var configuration = (IServerObjectConfiguration2)serverObjectAdmin.CreateConfiguration();
  8.     // release the name of the Service, required
  9.     configuration.Name = serviceName;
  10.     // release the type of service, such as: MapServer, GeocodeServer
  11.     configuration.TypeName = ServiceConfigurationTypeName;
  12.     configuration.Description = serviceName;
  14.     // Service Description
  15.     SetDefaultServerConfigurations(configuration, mapFilePath, serverName);
  17.     // add service to the Server
  18.     serverObjectAdmin.AddConfiguration(configuration);
  20.     // start the service
  21.     serverObjectAdmin.StartConfiguration(configuration.Name, configuration.TypeName);
  22. }

This is to set the default values of my organization:

private static void SetDefaultServerConfigurations(IServerObjectConfiguration2 configuration, string mapFilePath, string serverName)
    var properties = configuration.Properties;
    // Set the path of the file
    properties.SetProperty("FilePath", mapFilePath);
    // image output directory
    properties.SetProperty("outputdir", "c:\\arcgisserver\\arcgisoutput");
    // image output virtual path
    properties.SetProperty("VirtualOutPutDir", "http://" + serverName + "/arcgisoutput");
    // image type supported by
    properties.SetProperty("SupportedImageReturnTypes", "URL");

(there are more settings that can be found here)


I found that it is best to look at existing services, for that I added the capability of getting your service settings in XML format:

  1. public static string GetServiceConfiguration(string serverName, string serviceName)
  2. {
  3.     IGISServerConnection gisServerConnection = new GISServerConnectionClass();
  4.     gisServerConnection.Connect(serverName);
  5.     var serverObjectAdmin = gisServerConnection.ServerObjectAdmin;
  7.     var configuration = (IServerObjectConfiguration4)serverObjectAdmin.GetConfiguration(serviceName, ServiceConfigurationTypeName);
  9.     return configuration.Serialize();
  10. }

The output of this method looks like this:

  1. <ServerObjectConfiguration>
  2.   <Description>PublishDemoIi</Description>
  3.   <Properties>
  4.     <FilePath>C:\Install\MsdUtils\</FilePath>
  5.     <outputdir>c:\arcgisserver\arcgisoutput</outputdir>
  6.     <VirtualOutPutDir>http://server/arcgisoutput</VirtualOutPutDir>
  7.     <SupportedImageReturnTypes>URL</SupportedImageReturnTypes>
  8.     <MaxImageHeight>2048</MaxImageHeight>
  9.     <MaxRecordCount>50000</MaxRecordCount>
  10.     <MaxBufferCount>100</MaxBufferCount>
  11.     <MaxImageWidth>2048</MaxImageWidth>
  12.     <IsCached>false</IsCached>
  13.     <CacheOnDemand>false</CacheOnDemand>
  14.     <IgnoreCache>false</IgnoreCache>
  15.     <ClientCachingAllowed>true</ClientCachingAllowed>
  16.     <CacheDir>c:\arcgisserver\arcgiscache\GtmPublishDemoIi</CacheDir>
  17.     <SOMCacheDir>c:\arcgisserver\arcgiscache</SOMCacheDir>
  18.     <UseLocalCacheDir>true</UseLocalCacheDir>
  19.   </Properties>
  20.   <Extension>
  21.     <TypeName>FeatureServer</TypeName>
  22.     <Enabled>true</Enabled>
  23.     <Properties>
  24.       <EnableZDefaults>false</EnableZDefaults>
  25.       <ZDefaultValue>0</ZDefaultValue>
  26.     </Properties>
  27.     <Info>
  28.       <WebEnabled>true</WebEnabled>
  29.       <SupportsMSD>true</SupportsMSD>
  30.       <WebCapabilities>Query</WebCapabilities>
  31.     </Info>
  32.   </Extension>
  34.   <Extension>
  35.     <TypeName>...</TypeName>
  36.     <Enabled>false</Enabled>
  37.     <Properties>
  38.     </Properties>
  39.     <Info>
  40.     </Info>
  41.   </Extension>
  43.   <Info>
  44.     <WebEnabled>true</WebEnabled>
  45.     <WebCapabilities>Map,Query,Data</WebCapabilities>
  46.   </Info>
  47.   <IsPooled>true</IsPooled>
  48.   <MinInstances>1</MinInstances>
  49.   <MaxInstances>2</MaxInstances>
  50.   <InstancesPerContainer>1</InstancesPerContainer>
  51.   <WaitTimeout>60</WaitTimeout>
  52.   <IdleTimeout>-1</IdleTimeout>
  53.   <UsageTimeout>600</UsageTimeout>
  54.   <CleanupTimeout>30</CleanupTimeout>
  55.   <ServiceKeepAliveInterval>-1</ServiceKeepAliveInterval>
  56.   <StartupTimeout>300</StartupTimeout>
  57.   <Isolation>high</Isolation>
  58.   <StartupType>automatic</StartupType>
  59. </ServerObjectConfiguration>

As you can see the properties in the XML correspond perfectly with the properties settings.


To test the creation of the service you can look at ArcGis Server Manager:



Where you can tweak the settings (as you can see I had 5 tries till I got it right…).

Also you can test the service using the REST API :



Looking into the FeatureServer link you will find in the bottom “Supported Operations: Query” where you can test the Feature service queries:



Some points:

  1. Using PublishToServer needs MSD file located on the server.
  2. In order to use PublishToServer user must be an admin on the server (otherwise the call gisServerConnection.ServerObjectAdmin would fail)
  3. You must clear ArcGis rest API cache before using the service (or you won’t see it in the rest/services url) – for doing that automatically see my previous post: Clearing ArcGIS Server REST API Cache

I have posted the complete tool in my Codeplex project: ArcGisServerTools, MsdUtils, ArcGisServerUtils.



ArcGis Server Forum: Promote map service from one server stage to another in automated fashion?

Findleaf - Chinese Blog code

ArcObjects Forum: Publish MXD to server in ArcObjects C#


Keywords: MSD, ArcObjects, ArcGis Server, ESRI