环境:windowsxp sp3+IIS5.1+Arcgis server10
问题描述:WebService调用C++dll在XP下IIS5.1发布后始终没有返回值,但是在调试状态下一切正常。在网上泡了3天,总算解决了。
由于WebGis项目需求, 项目采取vs2010开发,语言采用C#及silverlight,GIS发布采用arcgis server10,通过arcgis silverlight api访问地图。
WebGis地图上的电力开关实时状态需要从另一套系统(配网监控系统,C++开发的)中获取,所有就用了webservice来实现,具体就是在配网监控系统中写了个webgis_service进程(守护的)和一个librealdata.dll(这两都是基于C/C++的),
其中在librealdata.dll提供了通过传入参数获取某些电力开关实时状态的接口,如下:
int ?LIBREALDATA_API __stdcall GetKgRealData(char *comenames,char** retval);
而webservice中调用如下(GisRealData.asmx.cs中):

?#region 实时数据获取类
?public class GisRealData : System.Web.Services.WebService
? ? {
? ? ? ? [WebMethod]
? ? ? ? public string HelloWorld()
? ? ? ? {
? ? ? ? ? ? return "Hello World";
? ? ? ? }
? ? ? ? [WebMethod]
? ? ? ? public byte[] GetKG_RealData(byte[] comenames)
? ? ? ? {
? ? ? ? ? ? IntPtr retptr;
? ? ? ? ? ? int retval = 0;
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? retval = GetKgRealData(comenames,out retptr);
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? string str = ex.Message;
? ? ? ? ? ? ? ? throw new Exception("获取数据失败!");
? ? ? ? ? ? }
? ? ? ? ? ? if (retval <= 0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return null;
? ? ? ? ? ? }
? ? ? ? ? ? byte[] retdata = new byte[retval];
? ? ? ? ? ? for (int i = 0; i < retval; i++) retdata[i] = Marshal.ReadByte(retptr,i);
? ? ? ? ? ? FreeRealDataMem(retptr);
? ? ? ? ? ? return retdata;
? ? ? ? ? ? //return Convert.ToBase64String(retdata);
? ? ? ? }
? [DllImport("C:xxxxdlllibrealdata.dll",CharSet = CharSet.Ansi,EntryPoint = "GetKgRealData",ExactSpelling = false)]
? ? ? ? public static extern int GetKgRealData(byte[] comenames,out IntPtr retval);
? ? ? ? [DllImport("C:xxxxdlllibrealdata.dll",EntryPoint = "FreeRealDataMem",ExactSpelling = false)]
? ? ? ? public static extern void FreeRealDataMem(IntPtr retval);
? ? }
? ? #endregion
}
在silverlight中添加服务引用

在silverlight中调用(MainPage.xaml.cs)
MainPage函数中如下:
{?
.....
? ? ? ? public GisRealDataSoapClient ? ?m_soapclient;
? //EndpointAddress real_address = new EndpointAddress(new Uri(Application.Current.Host.Source,"/GisRealData.asmx")); ? ? ? ?//VS2010调试用
? ? ? ? EndpointAddress real_address = new EndpointAddress(new Uri(Application.Current.Host.Source,"/WebGis/GisRealData.asmx")); ? //IIS发布用
? ? ? ? BasicHttpBinding real_BasicHttpBinding = new BasicHttpBinding();
? ? ? ? real_BasicHttpBinding.MaxBufferSize = 2147483647;
? ? ? ? real_BasicHttpBinding.MaxReceivedMessageSize = 2147483647;
? ? ? ? real_BasicHttpBinding.OpenTimeout = new TimeSpan(0,1,0);
? ? ? ? real_BasicHttpBinding.CloseTimeout = new TimeSpan(0,0);
#if DEBUG
? ? ? ? real_BasicHttpBinding.SendTimeout = new TimeSpan(18,10,00);
? ? ? ? real_BasicHttpBinding.ReceiveTimeout = new TimeSpan(18,00);
#else
? ? ? ? real_BasicHttpBinding.SendTimeout = new TimeSpan(0,5,00);
? ? ? ? real_BasicHttpBinding.ReceiveTimeout = new TimeSpan(0,00);
#endif
? ? ? ? m_soapclient = new GisRealDataSoapClient(real_BasicHttpBinding,real_address);
? ? ? ? m_soapclient.GetKG_RealDataCompleted += new EventHandler<GetKG_RealDataCompletedEventArgs>(GetKG_RealDataCompleted);
? ? ? ? m_soapclient.HelloWorldCompleted += new EventHandler<HelloWorldCompletedEventArgs>(HelloWorldCompleted);
? ? ? ? m_soapclient.HelloWorldAsync();
.....
}
//获取开关、刀闸实时数据,此函数在一个线程中调用
? ? ? ? public void GetKgRealData()
? ? ? ? {
? ? ? ? ? ? if (m_soapclient == null || m_kgparabyte == null) return;
? ? ? ? ? ? m_soapclient.GetKG_RealDataAsync(m_kgparabyte);
? ? ? ? }
?//WEB SERVICE测试
? ? ? ? public void HelloWorldCompleted(object sender,HelloWorldCompletedEventArgs e)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (e.Result != null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? HtmlPage.Window.Alert(e.Result.ToString());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception error)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? string errmsg = error.ToString();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //取得开关实时数据响应函数
? ? ? ? public void GetKG_RealDataCompleted(object sender,GetKG_RealDataCompletedEventArgs e)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (e.Result != null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? byte[] resultbyte = e.Result;
? ? ? ? ? ? ? ? ? ? WEBGIS_RETKGPARAM retkgdata = null;
? ? ? ? ? ? ? ? ? ? MyConvert.Byte2KGStruct(resultbyte,out retkgdata);
? ? ? ? ? ? ? ? ? ? ?//线程异步的委托更新UI用此种写法,不更新就不用了
? ? ? ? ? ? ? ? ? ? this.Dispatcher.BeginInvoke(() =>
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? RenderPDKGSymbols(retkgdata);
? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception error)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? string errmsg = error.ToString();
? ? ? ? ? ? }
? ? ? ? }
web.config配置如下:
<?xml version="1.0"?>
<!--
? 有关如何配置 ASP.NET 应用程序的详细消息,请访问
? http://go.microsoft.com/fwlink/?LinkId=169433
? -->
<configuration>
? <system.web>
? ? <compilation debug="true" targetFramework="4.0">
? ? </compilation>
? ? <httpRuntime maxRequestLength="65535" executionTimeout="36000" useFullyQualifiedRedirectUrl="false" />
? ? <webServices >
? ? ? <protocols >
? ? ? ? <add name="HttpSoap"/>
? ? ? ? <add name="HttpPost"/>
? ? ? ? <add name="HttpGet"/>
? ? ? ? <add name="Documentation"/>
? ? ? </protocols>
? ? </webServices>
? </system.web>
? <appSettings>
? ? <add key="SDE_SQLServerConnString" value="Data Source=10.1.1.57;UID=sa;PWD=xxxx;DATABASE=Esri_SDE "/>
? ? <add key="SQLServerConnString" value="Data Source=10.1.1.57;UID=sa;PWD=xxxx;DATABASE=WebGIS "/>
? ? <add key="MapServiceURL" value="http://10.1.1.57/ArcGIS/rest/services/webGIS_jx/MapServer"/>
? ? <add key="MapFullExtent" value="113.764813|38.266093|114.404081|37.662598"/>
? ? <add key="FeatureServiceURL" value="http://10.1.1.57/ArcGIS/rest/services/webGIS_layer"/>
? </appSettings>
? <system.serviceModel>
? ? <behaviors>
? ? ? <serviceBehaviors>
? ? ? ? <behavior name="mybehavior">
? ? ? ? ? <serviceMetadata httpGetEnabled="true"/>
? ? ? ? ? <serviceDebug includeExceptionDetailInFaults="false"/>
? ? ? ? ? <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
? ? ? ? </behavior>
? ? ? </serviceBehaviors>
? ? </behaviors>
? ? <bindings>
? ? ? <basicHttpBinding>
? ? ? ? <binding name="BasicHttpBinding_SymbolTableService" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"
? ? ? ? ? ? ? ? ?receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00">
? ? ? ? ? <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
? ? ? ? </binding>
? ? ? </basicHttpBinding>
? ? </bindings>
? ? <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
? ? <services>
? ? ? <service name="WebGIS.Web.SymbolTableService" behaviorConfiguration="mybehavior">
? ? ? ? <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SymbolTableService" contract="WebGIS.Web.SymbolTableService" />
? ? ? ? <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
? ? ? </service>
? ? </services>
? </system.serviceModel>
</configuration>
ServiceReferences.ClientConfig配置如下:
<configuration>
? ? <system.serviceModel>
? ? ? ? <bindings>
? ? ? ? ? ? <basicHttpBinding>
? ? ? ? ? ? ? ? <binding name="GisRealDataSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
? ? ? ? ? ? ? ? ? ? <security mode="None" />
? ? ? ? ? ? ? ? </binding>
? ? ? ? ? ? ? ? <binding name="BasicHttpBinding_SymbolTableService" maxBufferSize="2147483647"
? ? ? ? ? ? ? ? ? ? maxReceivedMessageSize="2147483647">
? ? ? ? ? ? ? ? ? ? <security mode="None" />
? ? ? ? ? ? ? ? </binding>
? ? ? ? ? ? </basicHttpBinding>
? ? ? ? </bindings>
? ? ? ? <client>
? ? ? ? ? ? <endpoint address="http://10.1.1.57/WebGis/GisRealData.asmx" binding="basicHttpBinding"
? ? ? ? ? ? ? ? bindingConfiguration="GisRealDataSoap" contract="GisRealDataRef.GisRealDataSoap"
? ? ? ? ? ? ? ? name="GisRealDataSoap" />
? ? ? ? ? ? <endpoint address="http://10.1.1.57/WebGis/SymbolTableService.svc"
? ? ? ? ? ? ? ? binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SymbolTableService"
? ? ? ? ? ? ? ? contract="SymbolTableRef.SymbolTableService" name="BasicHttpBinding_SymbolTableService" />
? ? ? ? </client>
? ? </system.serviceModel>
</configuration>
这样在IIS5.1下发布后,??m_soapclient.GetKG_RealDataAsync(m_kgparabyte)始终没有返回值(没进GetKG_RealDataCompleted函数),但是调用?m_soapclient.HelloWorldAsync()一切正常,有返回值,直接访问webserivce也能看到,如下:


后来在网上查了好几天,网上有一篇文章《webservice发布问题,部署iis后调用不成功》
有这么一句话“对应的应用池,设置默认设置-->进程模型-->标识-->设置localsystem”
还有《C#的WebService调用VC++的DLL,VS2005程序运行DEBUG可行,但是其他机器访问就不行》中的“你可以在web.config里启用模拟,或者在iis6的应用程序池里的对应的网站的池的标识采用本地系统,或者将dll本身的安全性添加匿名账户访问权限”
最后试了半天,给dll目录添加匿名账户访问权限不行,IIS5.1没有应用程序池设置。
最后在web.config里启用模拟,问题解决了。
即在<system.web>中加上这句<identity impersonate="true" />。
N天后做别的测试,上传文件不行,于是然后设置了下虚拟目录属性为:写入等(全打上勾);

还有就是inetinfo.exe也报错。

莫名其妙的实时数据又取不到了(调试下没问题,上边提到的indentify也是true)。
后来在所调用的dll文件夹(上边提到的c:xxxx)属性中添加上匿名访问的用户,突然又可以了,如下:


真是无语了!