第一章 使用ArcGIS Engine 管理ArcGIS Server
1.1 原因在10版本以及之前的版本中,有一些用户通过ArcGIS Engine来管理ArcGIS Server,比如发布服务,停止服务等,对服务的管理是通过DCOM方式的,而在10.1中ArcGIS 不支持DOCM方式的连接,。如果你在代码中使用了Server库中的GISServerConnection或者GISClient库中的AGSServerConnection,在ArcGIS Server 10.1环境下,这些代码必须移除,如下面的代码: 如果强行执行,那么会有下面的错误: 1.2 解决ArcGIS Server在10.1版本中提供了ADMIN API,只要我们通过http请求构造相应的参数就行,对于ArcGIS Server的连接,我们可以看下desktop是如何连接的:从这两个图中就可以看出,在选择连接Server的时候,选择角色,选择服务的类型(SDS和ArcGIS Server),在10版本以及之前的版本的时候跟这个有较大区别,连接ArcGIS 10.1 for Server的代码如下(注释已经写出):public IServerObjectAdmin ConnectAGS(string host, string username, string password) { try { IPropertySet propertySet = new PropertySetClass(); propertySet.SetProperty("url", host); propertySet.SetProperty("ConnectionMode", esriAGSConnectionMode.esriAGSConnectionModeAdmin); propertySet.SetProperty("ServerType", esriAGSServerType.esriAGSServerTypeDiscovery); propertySet.SetProperty("user", username); propertySet.SetProperty("password", password); propertySet.SetProperty("ALLOWINSECURETOKENURL", true); //设置为false会弹出一个警告对话框 IAGSServerConnectionName3 pConnectName = new AGSServerConnectionNameClass() as IAGSServerConnectionName3;//10.1新增接口 pConnectName.ConnectionProperties = propertySet; IAGSServerConnectionAdmin pAGSAdmin = ((IName)pConnectName).Open() as IAGSServerConnectionAdmin; token = GenerateAGSToken_RESTAdmin(host, "arcgis", "arcgis"); return pAGSAdmin.ServerObjectAdmin; } catch (Exception exc) { Console.WriteLine("连接失败: {0}. Message: {1}", host, exc.Message); return null ; } }ConnectAGS("http://192.168.110.136:6080/arcgis/admin", "arcgis", "arcgis");当获得了IAGSServerConnectionAdmin 这个接口我们进而可以获取IServerObjectAdmin,IServerObjectAdmin接口,在帮助中看到了IDiscoveryServerObjectAdmin接口,该接口的方法和属性如下:我欣喜若狂,因为这些和ArcGIS Server的Admin几乎是对应的,实现该接口的类不能被实例化,必须通过其他对象获取。但是不幸的是我在dll中并没有发现这个。1.2.1 一个猜想既然这个接口不能自己new,必须通过其他的实例化,那么这个对象是谁?我们很自然的想到应该在连接成功之后就返回这个对象,该对象实现的接口如下:我们注意下IRESTServerObjectAdmin 接口,字面意思就是通过rest方式跟Server打交道,而该接口只被一个类实现,该类就DiscoveryServerObjectAdmin如果连接成功返回的真是DiscoveryServerObjectAdmin对象,那么我们QI到IRESTServerObjectAdmin上是没有问题的,结果正如我猜想的一样,有图为证: 以上是我的个人猜想,但是不知道为什么dll中没找到这个接口,还是ESRI故意将这个接口隐藏起来了。1.3 AO操作当连接上ArcGIS Server,我们获取了IAGSServerConnectionAdmin,通过该对象我们获取了IServerObjectAdmin,通过该对象可以对Server进行管理1.3.1 更改实例数 private void ChangInstance(IServerObjectAdmin pSAdmin, IServerObjectConfiguration pConf, int pMin, int pMax) { IEnumServerObjectConfiguration pEnServerConf = pSAdmin.GetConfigurations(); IServerObjectConfiguration pSConf = pEnServerConf.Next(); IServerObjectConfiguration pSOConfig = null; while (pSConf != null) { if (pSConf.Name == pConf.Name && pSConf.TypeName == pConf.TypeName) { pSOConfig = pSConf; break; } pSConf = pEnServerConf.Next(); } if (pSConf != null) { pSConf.MinInstances = pMin; pSOConfig.MaxInstances = pMax; pSAdmin.UpdateConfiguration(pSOConfig); } }1.3.2 停止服务pServerAdmin.StopConfiguration("Flow", "MapServer");1.3.3 删除服务 pServerAdmin.DeleteConfiguration("BusSimulation/DataPrep", "MapServer");//如果自己建立了目录请按照这种方式写,不然出错1.4 REST方式操作ArcGIS 10.1 for Server可以通过http请求的方式访问,server接到请求后,然后响应,响应的结果是json格式的,对json格式我们可以自己去解析,但是这个很麻烦,在10.1中增加了很多对json格式处理的接口IJSONReader2,IJSONWriter等很多,我在这里偷懒直接使用了AO中自带的接口,如果不用AO中的这些接口,自己借助一些json的解析工具如:JSON.NET也是可以的。1.4.1 获取token public string GenerateAGSToken_RESTAdmin(string restAdmin, string username, string password) { try { if (restAdmin.EndsWith("\\")) { restAdmin = restAdmin.Substring(0, restAdmin.Length - 1); } if (restAdmin.EndsWith("services")) { restAdmin = restAdmin.Substring(0, restAdmin.Length - 9); } string loginUrl = restAdmin + "/generateToken"; WebRequest request = WebRequest.Create(loginUrl); request.Method = "POST"; string credential = "username=" + username + "&password=" + password + "&client=requestip&expiration=&f=json"; byte[] content = Encoding.UTF8.GetBytes(credential); request.ContentLength = content.Length; request.ContentType = "application/x-www-form-urlencoded"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); IJSONReader2 pJsonReader = new JSONReaderClass(); IJSONObject pOb = pJsonReader.ParseJSONString(result) as IJSONObject; string token; if (pOb.TryGetValueAsString("token", out token)) { } return token; } catch { return ""; } }//""表示根目录 public bool DeleteService_RESTAdmin(string restAdmin, string username, string password, string serviceName,string pType,string pFolder ) { try { //string token = GenerateAGSToken_RESTAdmin(restAdmin, username, password); restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin; string serviceUrl = restAdmin + "/services" +pFolder+"/"+ serviceName + "." + pType + "/delete"; WebRequest request = WebRequest.Create(serviceUrl); string postcontent = "f=pjson&token=" + token; Byte[] content = Encoding.UTF8.GetBytes(postcontent); request.ContentLength = content.Length; request.ContentType = "application/x-www-form-urlencoded"; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); return result.Contains("success"); } catch { return false; } }1.4.2 停止服务 public bool StopService_RESTAdmin(string restAdmin, string username, string password, string serviceName, string pType, string pFolder) { try { // string token = GenerateAGSToken_RESTAdmin(restAdmin, username, password); restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;if (pFolder.Length > 0) { pFolder = pFolder.StartsWith("/") ? pFolder : "/" + pFolder; } string serviceUrl = restAdmin + "/services" +pFolder+"/"+ serviceName + "." + pType + "/stop"; WebRequest request = WebRequest.Create(serviceUrl); string postcontent = "f=pjson&token=" + token; Byte[] content = Encoding.UTF8.GetBytes(postcontent); request.ContentLength = content.Length; request.ContentType = "application/x-www-form-urlencoded"; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); return result.Contains("success"); } catch { return false; } }1.4.3 启动服务 public bool StartService_RESTAdmin(string restAdmin, string username, string password, string serviceName,string pServiceType,string pFolder) { try { // string token = GenerateAGSToken_RESTAdmin(restAdmin, username,password); restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;if (pFolder.Length > 0) { pFolder = pFolder.StartsWith("/") ? pFolder : "/" + pFolder; } string serviceUrl = restAdmin + "/services" + pFolder + "/" + serviceName + "." + pServiceType + "/start";//服务名称+"."+类型 WebRequest request = WebRequest.Create(serviceUrl); string postcontent = "f=pjson&token=" + token; Byte[] content = Encoding.UTF8.GetBytes(postcontent); request.ContentLength = content.Length; request.ContentType = "application/x-www-form-urlencoded"; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); return result.Contains("success"); } catch { return false; } }1.4.4 获取服务的目录,名称和类型 //目录,服务名称,类型 Dictionary<string, Dictionary<string, string>> pServiceType = new Dictionary<string, Dictionary<string, string>>(); Dictionary<string, string> pDic = new Dictionary<string, string>(); public Dictionary<string, Dictionary<string, string>> ListServices_RESTAdmin(string restAdmin, string username, string password, string folder) { try { //使用WebRequest 发送请求 restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin; string serviceUrl = restAdmin + "/" + folder; WebRequest request = WebRequest.Create(serviceUrl); string postcontent = "f=json&token=" + token; // json格式 Byte[] content = Encoding.UTF8.GetBytes(postcontent); request.ContentLength = content.Length; // request.ContentType ="application/x-www-form-urlencoded"; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); int index = result.IndexOf("services"); Dictionary<string, string> pSer = new Dictionary<string, string>(); IJSONReader2 pJsonReader = new JSONReaderClass(); IJSONObject pOb = pJsonReader.ParseJSONString(result) as IJSONObject; //"folders":["BusSimulation","System","Utilities"] //根目录 pServiceType.Add("/", new Dictionary<string, string>()); IJSONArray pFodArr; if(pOb.TryGetValueAsArray("folders",out pFodArr)) { for (int i = 0; i < pFodArr.Count; i++) { pServiceType.Add(pFodArr.get_Value(i).ToString(), new Dictionary<string, string>()); } } if (pOb.MemberExists("services")) { object pJs; if (pOb.TryGetValue("services", out pJs)) { if (pJs is IJSONArray) { IJSONArray pArray = pJs as IJSONArray; for (int i = 0; i < pArray.Count; i++) { if (pArray.get_Value(i) is IJSONObject) { IJSONObject pType = pArray.get_Value(i) as IJSONObject; // {"folderName":"/","serviceName":"GZCache","type":"MapServer","description":""} string folderName; //服务的目录 if(pType.TryGetValueAsString("folderName",out folderName)) { } string serviceName; //服务的名称 if(pType.TryGetValueAsString("serviceName",out serviceName)) { } string AGSType; //服务的类型 if(pType.TryGetValueAsString("type",out AGSType)) { } pServiceType[folderName].Add(serviceName, AGSType); } } } } } } catch { } return pServiceType; }1.4.5 删除服务 public bool DeleteService_RESTAdmin(string restAdmin, string username, string password, string serviceName,string pType,string pFolder ) { try { //string token = GenerateAGSToken_RESTAdmin(restAdmin, username, password); restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;if (pFolder.Length > 0) { pFolder = pFolder.StartsWith("/") ? pFolder : "/" + pFolder; } string serviceUrl = restAdmin + "/services" +pFolder+"/"+ serviceName + "." + pType + "/delete"; WebRequest request = WebRequest.Create(serviceUrl); string postcontent = "f=pjson&token=" + token; Byte[] content = Encoding.UTF8.GetBytes(postcontent); request.ContentLength = content.Length; request.ContentType = "application/x-www-form-urlencoded"; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); return result.Contains("success"); } catch { return false; } }1.4.6 服务是否停止 public bool GetStatus_RESTAdmin(string restAdmin, string username, string password, string serviceName, string pServiceType, string pFolder) { try { // string token = GenerateAGSToken_RESTAdmin(restAdmin, username,password); restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin; string serviceUrl = restAdmin + "/services" + pFolder + "/" + serviceName + "." + pServiceType + "/status";//服务名称+"."+类型 WebRequest request = WebRequest.Create(serviceUrl); string postcontent = "f=pjson&token=" + token; Byte[] content = Encoding.UTF8.GetBytes(postcontent); request.ContentLength = content.Length; request.ContentType = "application/x-www-form-urlencoded"; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(content, 0, content.Length); requestStream.Close(); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string result = reader.ReadToEnd(); return result.Contains("STOPPED"); } catch { return false; } }1.5 小结在1.3和1.4我们分别用了AO的方式和REST的方式管理了ArcGIS 10.1 for Server,关于两种方法各有利弊,在这里我略总结如下: 第二章 使用ArcGIS Engine 访问ArcGIS Server2.1 以前是如何访问的上面提到了我们以前通过DCOM的方式也就是本地连接来管理ArcGIS Server,而管理ArcGIS Server是通过IAGSServerConnectionAdmin接口,以前我们通过IGISServerConnection接口的connect方法来获取connect方法只有一个参数就是机器所在的位置,而该方法“隐性”的使用当前操作系统登陆用户名和密码去验证,为了保证连接的正确,当前的用户名必须在agsadmin组或者agsuser组,而前者是用来管理Server的,后者是用来访问Server的服务的,如果当前登陆的操作系统的账户不属于这两个组,那么就会报错,现在这种方式不存在了。 private IServerObjectAdmin5 Admin() { ESRI.ArcGIS.Server.IGISServerConnection pServerConn = new ESRI.ArcGIS.Server.GISServerConnectionClass(); pServerConn.Connect("esri-LiuYu"); IServerObjectAdmin5 pServerAdim = pServerConn.ServerObjectAdmin as IServerObjectAdmin5; return pServerAdim; }在管理ArcGIS 10.1 for Server的时候我们必须”显性”的指定用户名和密码,所以该接口在10.1的时候肯定是不能用,正如我们开始提到的那样,会报错。2.2 IAGSServerConnection接口还能用吗?IAGSServerConnection这个接口也是可以用来连接,该接口被AGSServerConnectionClass类实现,但是这个类是不可以自己实例化的,必须通过其他类创建,这个类实现的接口如下:我们现在用user的身份连接,代码如下: public List<IAGSServerObjectName> ConnectUserAGS(string host, string username, string password) { try { List<IAGSServerObjectName> pList = new List<IAGSServerObjectName>(); IPropertySet propertySet = new PropertySetClass(); propertySet.SetProperty("url", host); propertySet.SetProperty("ConnectionMode", esriAGSConnectionMode.esriAGSConnectionModeConsumer); propertySet.SetProperty("user", username); propertySet.SetProperty("password", password); //打开连接 // IAGSServerConnectionFactory pFactory = new AGSServerConnectionFactory(); //Type factoryType = Type.GetTypeFromProgID( // "esriGISClient.AGSServerConnectionFactory"); //IAGSServerConnectionFactory agsFactory = (IAGSServerConnectionFactory) // Activator.CreateInstance(factoryType); IAGSServerConnectionName3 pConnectName = new AGSServerConnectionNameClass() as IAGSServerConnectionName3;//10.1新增接口 pConnectName.ConnectionProperties = propertySet; IAGSServerConnection pConnection = ((IName)pConnectName).Open() as IAGSServerConnection; //IAGSServerConnection pConnection = pFactory.Open(propertySet, 0); IAGSEnumServerObjectName pServerObjectNames = pConnection.ServerObjectNames; pServerObjectNames.Reset(); IAGSServerObjectName agsServerObjectName = pServerObjectNames.Next(); while (agsServerObjectName != null) { pList.Add(agsServerObjectName); agsServerObjectName = pServerObjectNames.Next(); } return pList; }在这里我取回List中的第一个,然后在MapControl中显示,代码如下: List<IAGSServerObjectName> pList = pServerMnt.ConnectUserAGS("http://192.168.110.136:6080/arcgis/rest/services", "", ""); // IRESTServerObjectAdmin pRest = pServerAdmin as IRESTServerObjectAdmin; ESRI.ArcGIS.Carto.IMapServerLayer pMapServerLayer = new ESRI.ArcGIS.Carto.MapServerLayerClass(); IName pName = (IName)pList[0]; IAGSServerObject pServerObject = (IAGSServerObject)pName.Open(); IMapServer pMapServer = (IMapServer)pServerObject; pMapServerLayer.ServerConnect(pList[0], pMapServer.DefaultMapName); axMapControl1.AddLayer(pMapServerLayer as ILayer); axMapControl1.Refresh();效果如下:看到结果,这个问题已经有了答案了,对于以用户的身份连接ArcGIS Server的话,我们只需要修改下IPropertySet属性即可 。
文章来源: