這幾天友人同學說他在COM利用服務標記調用WCF服務的時候遇到一個問題,就是他返回的的Soap消息 大於65536這個wsHttpBinding的缺省值,引發調用錯誤。需要將MaxReceivedMessageSize更改成可以容納 大消息內容的值。在我前面的三篇文章中使用的都是缺省的wsHttpBinding,所以不存在這個問題。現在 需要更改缺省值自然就需要增加配置來達到目的。目前最關鍵的問題就是:是否能讓VB/VBA/Script來使 用配置文件呢?如果可以,那如何讓VB,VBA, Script來使用配置文件中定義的綁定呢?
在多方搜尋探索嘗試之後,終於找到了解決方案,那就是只要將配置文件放在宿主文件的相同目錄, 並且將配置文件的名稱改成和宿主文件同名(包括擴展名)再加上.config之後,就可以讓VB/VBA/Script 來使用配置文件中定義的綁定去調用WCF服務。如果是vbs文件(vb script),由於執行vbs文件的是 cscript.exe或者wscript.exe,缺省情況下我們系統都是使用wscript.exe來執行的,這時候你可以把配 置文件放在系統目錄的system32下,名為wscript.exe.config.
如果是VBA宏的話,要看是word還是excel,或者其他。因為不同的類型其配置文件名不一樣。如果是 word,那麼配置文件名稱應該是WINWORD.EXE.config,如果是excel,配置文件名應該是: Excel.exe.config.其他類型依次類推。
如果是VB程序的話,假如我們的程序名為test.exe,那麼配置文件名稱為test.exe.config.
不過需要注意的是,如果COM(VB/VBA/Script)利用服務標記調用WCF服務需要使用配置文件的話,我們 只能使用類型化契約,不能使用mex契約和WSDL契約(具體如何使用類型化契約、MEX契約、WSDL契約,請 參看我以前的文章。COM(VB/VBA/Script)利用服務標記調用WCF服務之一使用類型化契約、COM (VB/VBA/Script)利用服務標記調用WCF服務之二使用MEX契約、COM(VB/VBA/Script)利用服務標記調用WCF 服務之三使用WSDL契約),這個可能和標記字符串有關系,細心的同學可能發現,類型化標記字符串中的 binding和.net中的配置是一樣的,而MEX和WSDL標記字符串中的binding是固定的。 為了更加清晰一點 ,下面就以VBS中以類型化契約服務標記調用WCF為例,由於這個系列的WCF服務端基本都相同,不過這次 由於我們為了制造返回超過65536個字符的消息所以對服務端的Service1.svc.cs文件做部分更改,更改後 的文件內容如下:using System;
using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WCFServiceMoniker { public class Service1 : IService1 { public string SayHello(string yourwords) { return string.Format("Hello World! You entered: {0}{1}", yourwords,new string('A',65536) ); } } }
注:相比較以前的服務端,只是多增加了65536個A作為返回值。同樣,服務端的配置文件也要做相應 的變更:關於服務定義一節更改成如下:
<system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_ZXG" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="52428800" maxReceivedMessageSize="6553600" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> <readerQuotas maxDepth="32" maxStringContentLength="819200" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="Message"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true" /> </security> </binding> </wsHttpBinding> </bindings> <services> <service name="WCFServiceMoniker.Service1" behaviorConfiguration="WCFServiceMoniker.Service1Behavior"> <!-- Service Endpoints --> <endpoint address="" binding="wsHttpBinding" bindingConfiguration ="WSHttpBinding_ZXG" contract="WCFServiceMoniker.IService1"> <!-- Upon deployment, the following identity element should be removed or replaced to reflect the identity under which the deployed service runs. If removed, WCF will infer an appropriate identity automatically. --> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WCFServiceMoniker.Service1Behavior"> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
注:比較以前的,主要是更改了maxReceivedMessageSize,maxBufferPoolSize, maxStringContentLength的值。
好了服務端更改好之後,下面我們需要對客戶端進行部分更改。
首先我們要准備一個客戶端的配置文件,該文件和我們一般的.net配置文件差不多,如下所示:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IService1" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="5242880" maxReceivedMessageSize="655360" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> <readerQuotas maxDepth="32" maxStringContentLength="819200" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="Message"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true" /> </security> </binding> </wsHttpBinding> </bindings> <client> <endpoint address="http://zxg/WCFServiceMoniker/Service1.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="IService1" name="WSHttpBinding_IService1"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>
將配置文件命名為wscript.exe.config,並將其放到系統目錄的system32目錄中
我們可以使用以前的Client.dll文件,不需要做任何改動,不過,我們需要對 CallWCFService_TypedContract.vbs文件微小修改,在標記字符串中增加 bindingConfiguration=WSHttpBinding_IService1,告訴系統使用這個配置文件中定義的綁定,修改之後 的文件如下:
'--------------------------------------------------------------- ' Typed Contract service moniker example '--------------------------------------------------------------- ' Create a service moniker object using a strongly typed contract ' This references the address, a standard binding type and the ' locally registered COM-visible contract ID monikerString = "service:address='http://localhost/WCFServiceMoniker/Service1.svc'" monikerString = monikerString + ", binding=wsHttpBinding, bindingConfiguration=WSHttpBinding_IService1" monikerString = monikerString + ", contract={4FBDA94E-8B89-32EC-BC28-2A0A5E9B7C74}" ' Create the service moniker object Set serviceMoniker = GetObject(monikerString) ' Call the service operations using the moniker object 'WScript.Echo serviceMoniker.SayHello("I am LazyBee") msgbox serviceMoniker.SayHello("I am LazyBee,"+chr(13)) 'msgbox serviceMoniker.SayHello("Ok") Set serviceMoniker= nothing
至此,所有更改都已完成,可以直接運行測試,一切ok!好了我可以回家了……
文章來源:http://www.cnblogs.com/LazyBee/