现在的位置: 首页 > 综合 > 正文

COM(VB/VBA/Script)利用服务标记调用WCF服务之四:使用配置文件

2013年08月02日 ⁄ 综合 ⁄ 共 6184字 ⁄ 字号 评论关闭
COM(VB/VBA/Script)利用服务标记调用WCF服务之四:使用配置文件

LazyBeehttp://lazybee.cnblogs.com/

   这几天友人同学说他在COM利用服务标记调用WCF服务的时候遇到一个问题,就是他返回的的Soap消息大于65536这个wsHttpBinding的缺省值,引发调用错误。需要将MaxReceivedMessageSize更改成可以容纳大消息内容的值。在我前面的三篇文章中使用的都是缺省的wsHttpBinding,所以不存在这个问题。现在需要更改缺省值自然就需要增加配置来达到目的。目前最关键的问题就是:是否能让VB/VBA/Script来使用配置文件呢?如果可以,那如何让VB,VBA, Script来使用配置文件中定义的绑定呢? 在多方搜寻探索尝试之后,终于找到了解决方案,那就是只要将配置文件放在宿主文件的相同目录,并且将配置文件的名称改成和宿主文件同名(包括扩展名)再加上.config之后,就可以让VB/VBA/Script来使用配置文件中定义的绑定去调用WCF服务。

  1. 如果是vbs文件(vb script),由于执行vbs文件的是cscript.exe或者wscript.exe,缺省情况下我们系统都是使用wscript.exe来执行的,这时候你可以把配置文件放在系统目录的system32下,名为wscript.exe.config.
  2. 如果是VBA宏的话,要看是word还是excel,或者其他。因为不同的类型其配置文件名不一样。如果是word,那么配置文件名称应该是WINWORD.EXE.config,如果是excel,配置文件名应该是:Excel.exe.config.其他类型依次类推。
  3. 如果是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>

注:比较以前的,主要是更改了maxReceivedMessageSizemaxBufferPoolSize, maxStringContentLength的值。

 

好了服务端更改好之后,下面我们需要对客户端进行部分更改。

  1.   首先我们要准备一个客户端的配置文件,该文件和我们一般的.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>

  2. 将配置文件命名为wscript.exe.config,并将其放到系统目录的system32目录中
  3. 我们可以使用以前的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://msdn.microsoft.com/zh-cn/library/ms752245.aspx

       http://msdn.microsoft.com/zh-cn/library/ms734731.aspx


抱歉!评论已关闭.