• ArcGIS 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
    所有的这些都是AO的操作,对于习惯使用AE的人来说,这些都很熟悉,唯一不同的是,Server不能用new去创建对象,细心人会发现在创建
    地图文档的时候,使用的是CreateObject的方式,如下面语句
    IMapDocument pMapDocument = serverContext.CreateObject("esriCarto.MapDocument") as IMapDocument;

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

    如果是fat格式就不用上述设置,毕竟NTFS格式安全系数比较高。至于Linux,懒羊羊没有做过,尝试过的朋友可以发表一下心得体会

    还有一点必须主要的,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 接口功能十分强大,建议去查一下帮助,
    对其加深了解。
    实际上,上述的操大多数都是常规的操作,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;
        }

    一起学习GIS及其二次开发,一起进步!
  • 相关阅读:
    一些技术摘选及随想
    新技术学习方法如何学习一门新编程语言(Lua)?
    什么时候该用ASSERT?
    MFC是否过时?如何学习MFC?
    Windows桌面开发者的必备软件
    Comet技术选择,论Is node.js best for Comet?
    关于C/C++内存管理一些乱讲
    debug
    C语言趣味题目
    CSS之简单的双引号
  • 原文地址:https://www.cnblogs.com/tuncaysanli/p/1423937.html
Copyright © 2020-2023  润新知