Server操作Mxd文件详细讲解(转载)

Server发布地图都是基于Mxd去发布的,这点与IMS使用axl文件差不多。一般来说,发布后mxd尽可能不要修改,或者在通过使用arcMap进行编辑后在重新发布。
修改mxd会导致地图服务发生变化,因此,相对来说是一种危险的操作。但有时客户需要对Mxd进行修改,自定义的添加修改图层,并重新发布服务。
当然,这些苛刻的需求server同样可以应付,但懒羊羊还是不建议这样做。方法总是有的,越危险的事也就越有趣。懒羊羊还是跟大家分享一下这方面的心得吧。

下面函数实现添加一个图层到mxd文件,并设置样式。为更好的表达,函数使用返回操作结果的字符串。
/// <summary>
        /// 添加图层到Mxd文件
        /// </summary>
        /// <param name="serverContext">IServerContext</param>
        /// <param name="nfc">新图层对应的要素集</param>
        /// <param name="groupIndex">复合图层的序号</param>
        /// <param name="mxdPath">mxd所在的路径</param>
        /// <param name="picPath">用于对图层渲染的图片</param>
        /// <returns></returns>
        public string addLayerInMxd(IServerContext serverContext, IFeatureClass nfc, int groupIndex, string mxdPath,string picPath)
        {
            IMapServer pMapServer = serverContext.ServerObject as IMapServer;
            IMapServerObjects pMapServerObjs = pMapServer as IMapServerObjects;
            IMap pMap = pMapServerObjs.get_Map(pMapServer.DefaultMapName);
            bool hasLayer = hasTheLayer(pMap, nfc.AliasName);
            if (hasLayer) return "已存在该命名图层,操作未能完成";  //如果图层已经存在了,那就不添加
            if (groupIndex >= pMap.LayerCount) return "组合图层序号越界,操作未能完成";
            IMapLayers mapLayer = pMap as IMapLayers;
            IGroupLayer gLayer = pMap.get_Layer(groupIndex) as IGroupLayer;
            IFeatureLayer fl = serverContext.CreateObject("esriCarto.FeatureLayer") as IFeatureLayer;
            fl.FeatureClass = nfc;
            fl.Name = nfc.AliasName;
            //设置样式
            ISimpleRenderer pRen = serverContext.CreateObject("esriCarto.SimpleRenderer") as ISimpleRenderer;
            IGeoFeatureLayer pGeoLayer = fl as IGeoFeatureLayer;
            IPictureMarkerSymbol picMark = serverContext.CreateObject("esriDisplay.PictureMarkerSymbol") as IPictureMarkerSymbol;
            picMark.Size = 20;
            picMark.CreateMarkerSymbolFromFile(esriIPictureType.esriIPictureBitmap, picPath);
            pRen.Symbol = (ISymbol)picMark;
            pGeoLayer.Renderer = (IFeatureRenderer)pRen;
            mapLayer.InsertLayerInGroup(gLayer, pGeoLayer as ILayer, false, 3);

            //获取pMapDocument对象
            IMxdContents pMxdC;
            pMxdC = pMap as IMxdContents;
            IMapDocument pMapDocument = serverContext.CreateObject("esriCarto.MapDocument") as IMapDocument;
            pMapDocument.Open(mxdPath, "");
            pMapDocument.ReplaceContents(pMxdC);
            if (pMapDocument == null) return "文档为空不能完成操作";
            //检查地图文档是否是只读
            if (pMapDocument.get_IsReadOnly(mxdPath) == true)
            {
                return "地图文档只读,未能完成操作";
            }
            //根据相对的路径保存地图文档
            pMapDocument.Save(pMapDocument.UsesRelativePaths, false);
            return "操作成功";
        }

/// <summary>
        /// 是否存在layerName为别名的图层
        /// </summary>
        /// <param name="pMap"></param>
        /// <param name="layerName"></param>
        /// <returns></returns>
        public bool hasTheLayer(IMap pMap, string layerName)
        {
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                ILayer pLayer = pMap.get_Layer(i);
                if (pLayer.Name == layerName)
                    return true;
                if (pLayer is ICompositeLayer)
                {
                    ICompositeLayer comLayer = pLayer as ICompositeLayer;
                    for (int j = 0; j < comLayer.Count; j++)
                    {
                        ILayer cLayer = comLayer.get_Layer(j);
                        if (cLayer.Name == layerName)
                            return true;
                    }
                }
            }
            return false;
        }

 

下面是根据图层名删除图层的操作
public string removeLayerFromMxd(IServerContext serverContext, layerName,string mxdPath)
        {
            IMapServer pMapServer = serverContext.ServerObject as IMapServer;
            IMapServerObjects pMapServerObjs = pMapServer as IMapServerObjects;
            IMap pMap = pMapServerObjs.get_Map(pMapServer.DefaultMapName);
            IMapLayers pMapLayers = pMap as IMapLayers;
            
            ILayer removeLayer = getLayerByName(serverContext, layerName);
            if (removeLayer == null)
                return "操作失败,找不到要删除的图层";
            pMapLayers.DeleteLayer(removeLayer);
            //获取pMapDocument对象
            IMxdContents pMxdC = pMap as IMxdContents; ;
            IMapDocument pMapDocument = serverContext.CreateObject("esriCarto.MapDocument") as IMapDocument;
            pMapDocument.Open(mxdPath, "");
            pMapDocument.ReplaceContents(pMxdC);
            if (pMapDocument == null) return "操作失败,地图文档为空";
            //检查地图文档是否是只读
            if (pMapDocument.get_IsReadOnly(mxdPath) == true)
            {
                return "操作失败,地图文档只读";
            }
            //根据相对的路径保存地图文档
            pMapDocument.Save(pMapDocument.UsesRelativePaths, false);
            return "操作成功";
        }

/// <summary>
        /// 是否存在layerName为别名的图层
        /// </summary>
        /// <param name="pMap"></param>
        /// <param name="layerName"></param>
        /// <returns></returns>
        public bool hasTheLayer(IMap pMap, string layerName)
        {
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                ILayer pLayer = pMap.get_Layer(i);
                if (pLayer.Name == layerName)
                    return true;
                if (pLayer is ICompositeLayer)
                {
                    ICompositeLayer comLayer = pLayer as ICompositeLayer;
                    for (int j = 0; j < comLayer.Count; j++)
                    {
                        ILayer cLayer = comLayer.get_Layer(j);
                        if (cLayer.Name == layerName)
                            return true;
                    }
                }
            }
            return false;
        }

当然,通过代码对服务器文件进行读写,还必须要注意网络的安全设置。
首先要确保有足够的权限对Mxd进行修改。
懒羊羊要指出,所谓的权限,第一是确保你的Server具有足够的授权。第二,服务器文件必须有足够的写入权限。
对于第二点,主要是考虑磁盘格式。网络开发人员都知道,NTFS格式下面,要访问文件,必须设置安全属性。
设置方法如下。
1。在服务器Mxd文件右键属性--点击"安全"标签
2.查找soc用户
3.给soc用户写入的权限。
懒羊羊这里只是举个例子,看官们只管使用自己的soc用户就行了。






还有一点必须主要的,Mxd更改以后,地图服务是没有发生变化的,所发布的地图一直驻留在内存中。因此,这时候需要更新一下地图服务。
方法有很多,最傻瓜最直接的方法就是跑到机房去重启mxd所对应的service。但是,懒羊羊比较懒,所以,还是希望通过代码去控制,update
一下。下面是更新地图服务的函数
private void updateService(string serviceName,string serverName)
    {
        ServerConnection pServerConnection = new ESRI.ArcGIS.Server.WebControls.ServerConnection(serverName);//地图服务机器名
        pServerConnection.Connect();
        IServerObjectAdmin pServerSOA = pServerConnection.ServerObjectAdmin;
        IServerObjectConfiguration pConfig = pServerSOA.GetConfiguration(serviceName, "MapServer");
        pServerSOA.UpdateConfiguration(pConfig);
    }

细心的朋友应该注意到了,这里面主要是使用了IServerObjectAdmin 接口,IServerObjectAdmin 接口功能十分强大,建议去查一下帮助,
对其加深了解。





描述
RemarksAny application that runs as a user account in the agsadmin user group on the ArcGIS Server can use the IGISServerConnection interface to connect to the ArcGIS Server and to get a reference to the ServerObjectAdmin. If the user account is not part of the agsadmin user group the ServerObjectAdmin property on IServerConnection will return an error. Applications that are running as accounts that can connect to the server but are not part of the agsadmin user group can use the ServerObjectManager property on IGISServerConnection to get a reference on the ServerObjectManager.
The IServerObjectAdmin interface has the necessary methods for an application to adminstrate both the set of server object configurations and types associated with the server, and to administer aspects of the server itself. The following administration functionality of the ArcGIS Server is exposed by methods and properties on IServerObjectAdmin :
Adminster server object configurations:

  • Add and delete server object configurations
  • Update a server object configuration's properties
  • Start, stop and pause server object configurations
  • Report the status of a server object configuration
  • Get all server object configurations and their properties
  • Get all server object types and their properties

Administer aspects of the server itself:

  • Add and remove server container machines
  • Get all server container machines
  • Add and remove server directories
  • Get all server directories
  • Configure the server's logging properties



如果是fat格式就不用上述设置,毕竟NTFS格式安全系数比较高。至于Linux,懒羊羊没有做过,尝试过的朋友可以发表一下心得体会
实际上,上述的操大多数都是常规的操作,AE程序员都能轻松搞定。但细微的地方还是要注意的,例如Server环境下创建新对象,文件的权限设置等等
对server的一些特性也必须了解。例如mxd更新以后必须重启服务,确保当前服务与地图文档一致,不然就可能导致灾难性的出错。

前面漏掉的一个函数现在补上
/// <summary>
    /// 通过图层名称返回图层
    /// </summary>
    /// <param name="pSOC">地图控件</param>
    /// <param name="LayerName">图层名称</param>
    /// <returns></returns>
    public static ILayer getLayerByName(IServerContext pSOC, string LayerName)
    {
        IMapServer pMapServer = pSOC.ServerObject as IMapServer;
        IMapServerObjects pMapServerObjs = pMapServer as IMapServerObjects;
        IMap pMap = pMapServerObjs.get_Map(pMapServer.DefaultMapName);
        //获取所有的图层
        for (int i = 0; i < pMap.LayerCount; i++)
        {
            ILayer lyr = pMap.get_Layer(i);
            if (lyr.Name == LayerName)
            {
                return lyr;
            }
            else if (lyr is ICompositeLayer)
            {
                //图层为复合图层,查找其子图层
                ICompositeLayer comLayer = lyr as ICompositeLayer;
                for (int j = 0; j < comLayer.Count; j++)
                {
                    ILayer cLayer = comLayer.get_Layer(j);
                    if (cLayer.Name == layerName)
                        return cLayer;
                }
            }
        }
        return null;
    }
原作者:懒洋洋

原地址:http://bbs.esrichina-bj.cn/ESRI/thread-35857-1-2.html

posted @ 2009-02-03 18:33  温景良(Jason)  Views(1631)  Comments(0Edit  收藏  举报