对 COM 客户端使用 WCF 标记

COM 示例演示如何使用 Windows Communication Foundation (WCF) 服务名字对象将 Web 服务集成到基于 COM 的开发环境,例如Microsoft Office Visual Basic for Applications(Office VBA)或 Visual Basic 6.0。 此示例由 Windows 脚本主机客户端(.vbs)、支持客户端库(.dll)和 Internet Information Services (IIS)托管的服务库(.dll)组成。 该服务是计算器服务,COM 客户端在服务上调用数学运算(添加、减法、乘法和除法)。 客户端活动在消息框窗口中可见。

注释

本示例的设置过程和生成说明位于本主题末尾。

该服务实现了一个合同,定义如下代码示例所示。

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);
    [OperationContract]
    double Subtract(double n1, double n2);
    [OperationContract]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2);
}

示例演示三种使用标记的备选方法:

  • 类型化合同 – 合同在客户端计算机上注册为 COM 可见类型。

  • WSDL 协定 – 协定以 WSDL 文档的形式提供。

  • 元数据交换协定 - 在运行时从元数据交换 (MEX) 终结点检索该协定。

类型化协定

若要对类型化协定用法使用标记,必须向 COM 注册服务协定的经适当属性化的类型。 首先,必须使用 ServiceModel 元数据实用工具工具(Svcutil.exe)生成客户端。 从客户端目录中的命令提示符运行以下命令以生成类型化的代理。

svcutil.exe /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost/servicemodelsamples/service.svc /out:generatedClient.cs

此类必须包括在项目中,并且应将项目配置为在编译时生成一个 COM 可见的已签名程序集。 应将以下属性包含在AssemblyInfo.cs文件中。

[assembly: ComVisible(true)]

生成项目后,使用 regasm 如下例所示注册 COM 可见类型。

regasm.exe /tlb:CalcProxy.tlb client.dll

创建的程序集应添加到全局程序集缓存中。 尽管并非严格要求,但这简化了运行时定位程序集的过程。 以下命令将程序集添加到全局程序集缓存。

gacutil.exe /i client.dll

注释

服务标记只要求进行类型注册,并不使用代理与服务通信。

ComCalcClient.vbs 客户端应用程序使用 GetObject 函数为服务构造代理,使用服务名字对象语法来指定服务的地址、绑定和协定。

Set typedServiceMoniker = GetObject(
"service4:address=http://localhost/ServiceModelSamples/service.svc, binding=wsHttpBinding,
contractType={9213C6D2-5A6F-3D26-839B-3BA9B82228D3}")

标记使用的参数将会指定:

  • 服务终结点的地址。

  • 客户端应该用来与该终结点连接的绑定。 在这种情况下,可以使用系统定义的 wsHttpBinding,不过可以在客户端配置文件中定义自定义绑定。 为了与 Windows 脚本主机一起使用,自定义绑定在与 Cscript.exe相同的目录中的 Cscript.exe.config 文件中定义。

  • 在终结点受支持的协定的类型。 此类型是在上面生成并注册的类型。 由于 Visual Basic 脚本不提供强类型 COM 环境,因此必须指定协定的标识符。 此 GUID 来自 interfaceID CalcProxy.tlb,可以使用 COM 工具(如 OLE/COM 对象查看器(OleView.exe)来查看它。 对于强类型化环境(如 Office VBA 或 Visual Basic 6.0),可以通过添加对类型库的显式引用,并声明代理对象的类型来替代协定参数。 这样还可在客户端应用程序开发过程中提供 IntelliSense 支持。

使用服务名字对象构造代理实例后,客户端应用程序可以在代理上调用方法,这会导致服务名字对象基础结构调用相应的服务作。

' Call the service operations using the moniker object
WScript.Echo "Typed service moniker: 100 + 15.99 = " & typedServiceMoniker.Add(100, 15.99)

运行示例时,操作响应将显示在 Windows Script Host 消息框窗口中。 此示例演示使用类型化名字对象发出 COM 调用以便与 WCF 服务进行通信的 COM 客户端。 尽管在客户端应用程序中使用 COM,但与服务的通信仅包括 Web 服务调用。

WSDL 协定

若要将别名与 WSDL 合同一起使用,无需任何客户端库注册,但必须通过带外方法(例如使用浏览器访问服务的 WSDL 终结点)检索服务的 WSDL 合同。 标记之后可以在执行时访问该协定。

ComCalcClient.vbs 客户端应用程序使用 FileSystemObject 访问本地保存的 WSDL 文件,然后再次使用该 GetObject 函数为服务构造代理。

' Open the WSDL contract file and read it all into the wsdlContract string
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("serviceWsdl.xml", ForReading)
wsdlContract = objFile.ReadAll
objFile.Close

' Create a string for the service moniker including the content of the WSDL contract file
wsdlMonikerString = "service4:address='http://localhost/ServiceModelSamples/service.svc'"
wsdlMonikerString = wsdlMonikerString + ", binding=WSHttpBinding_ICalculator, bindingNamespace='http://Microsoft.ServiceModel.Samples'"
wsdlMonikerString = wsdlMonikerString + ", wsdl='" & wsdlContract & "'"
wsdlMonikerString = wsdlMonikerString + ", contract=ICalculator, contractNamespace='http://Microsoft.ServiceModel.Samples'"

' Create the service moniker object
Set wsdlServiceMoniker = GetObject(wsdlMonikerString)

标记使用的参数将会指定:

  • 服务终结点的地址。

  • 客户端用于与该终结点连接的绑定和在其中定义该绑定的命名空间。 在本例中,使用了wsHttpBinding_ICalculator

  • 定义协定的 WSDL。 在本例中,这是从 serviceWsdl.xml 文件中读取的字符串。

  • 协定的名称和命名空间。 此标识是必需的,因为 WSDL 可能包含多个协定。

    注释

    默认情况下,WCF 服务将为使用的每个命名空间生成单独的 WSDL 文件。 这些属性与 WSDL 导入构造的使用相关联。 由于名字对象需要单个 WSDL 定义,因此服务必须使用此示例中所示的单个命名空间,或者必须手动合并单独的文件。

使用服务名字对象构造代理实例后,客户端应用程序可以在代理上调用方法,这会导致服务名字对象基础结构调用相应的服务作。

' Call the service operations using the moniker object
WScript.Echo "WSDL service moniker: 145 - 76.54 = " & wsdlServiceMoniker.Subtract(145, 76.54)

运行示例时,操作响应将显示在 Windows Script Host 消息框窗口中。 此示例演示使用具有 WSDL 协定的名字对象发出 COM 调用以便与 WCF 服务进行通信的 COM 客户端。

元数据交换协定

和 WSDL 协定一样,使用具有 MEX 协定的标记不需要注册任何客户端。 服务合同在执行过程中通过内部使用元数据交换机制进行检索。

ComCalcClient.vbs 客户端应用程序再次使用 GetObject 函数为服务构造代理。

' Create a string for the service moniker specifying the address to retrieve the service metadata from
mexMonikerString = "service4:mexAddress='http://localhost/servicemodelsamples/service.svc/mex'"
mexMonikerString = mexMonikerString + ", address='http://localhost/ServiceModelSamples/service.svc'"
mexMonikerString = mexMonikerString + ", binding=WSHttpBinding_ICalculator, bindingNamespace='http://Microsoft.ServiceModel.Samples'"
mexMonikerString = mexMonikerString + ", contract=ICalculator, contractNamespace='http://Microsoft.ServiceModel.Samples'"

' Create the service moniker object
Set mexServiceMoniker = GetObject(mexMonikerString)

标记使用的参数将会指定:

  • 服务元数据交换终结点的地址。

  • 服务终结点的地址。

  • 客户端用于与该终结点连接的绑定和在其中定义该绑定的命名空间。 在本例中,使用了wsHttpBinding_ICalculator

  • 协定的名称和命名空间。 此标识是必需的,因为 WSDL 可能包含多个协定。

使用服务名字对象构造代理实例后,客户端应用程序可以在代理上调用方法,这会导致服务名字对象基础结构调用相应的服务作。

' Call the service operations using the moniker object
WScript.Echo "MEX service moniker: 9 * 81.25 = " & mexServiceMoniker.Multiply(9, 81.25)

运行示例时,操作响应将显示在 Windows Script Host 消息框窗口中。 此示例演示使用具有 MEX 协定的名字对象发出 COM 调用以便与 WCF 服务进行通信的 COM 客户端。

设置和生成示例

  1. 确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。

  2. 若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。

  3. 在 Visual Studio 的开发人员命令提示符下,打开特定于语言的文件夹下的 \client\bin 文件夹。

    注释

    如果使用 Windows Vista、Windows Server 2008、Windows 7 或 Windows Server 2008 R2,请确保使用管理员权限运行命令提示符。

  4. 键入 tlbexp.exe client.dll /out:CalcProxy.tlb ,将 dll 导出到 tlb 文件。 预期会出现“类型库导出器警告”,但这不是问题,因为不需要使用泛型类型。

  5. 键入 regasm.exe /tlb:CalcProxy.tlb client.dll,向 COM 注册类型。 预期会出现“类型库导出器警告”,但这不是问题,因为不需要使用泛型类型。

  6. 键入gacutil.exe /i client.dll以将程序集添加到全局程序集缓存。

在同一计算机上运行示例

  1. 通过键入以下地址,测试是否可以使用浏览器访问服务: http://localhost/servicemodelsamples/service.svc 应在响应中显示确认页。

  2. 从语言特定的文件夹下的 \client 目录中运行 ComCalcClient.vbs。 客户端活动显示在消息框窗口中。

  3. 如果客户端和服务无法通信,请参阅 WCF 示例 故障排除提示。

跨计算机运行示例

  1. 在服务计算机上,创建名为 ServiceModelSamples 的虚拟目录。 示例中包含的 Setupvroot.bat 脚本可用于创建磁盘目录和虚拟目录。

  2. 将服务程序文件从 %SystemDrive%\Inetpub\wwwroot\servicemodelsamples 复制到服务计算机上的 ServiceModelSamples 虚拟目录。 请务必在 \bin 目录中包括文件。

  3. 将客户端脚本文件从特定于语言的文件夹下的 \client 文件夹复制到客户端计算机。

  4. 在脚本文件中,更改终结点定义的地址值以匹配服务的新地址。 请将地址中所有对“localhost”的引用替换为完整域名。

  5. 将 WSDL 文件复制到客户端计算机。 在 WSDL 文件 serviceWsdl.xml 中,将地址中任何对“localhost”的引用替换为一个完全限定的域名。

  6. 将 \client\bin 文件夹中的 Client.dll 库复制到客户端计算机上的目录(特定于语言的文件夹)。

  7. 在命令提示符下,导航到客户端计算机上的该目标目录。 如果使用 Windows Vista 或 Windows Server 2008,请确保以管理员身份运行命令提示符。

  8. 键入 tlbexp.exe client.dll /out:CalcProxy.tlb ,将 dll 导出到 tlb 文件。 预期会出现“类型库导出器警告”,但这不是问题,因为不需要使用泛型类型。

  9. 键入 regasm.exe /tlb:CalcProxy.tlb client.dll,向 COM 注册类型。 在运行命令之前,请确保路径已设置为包含 regasm.exe 的文件夹。

  10. 键入gacutil.exe /i client.dll以将程序集添加到全局程序集缓存。 在运行命令之前,请确保路径已设置为包含 gacutil.exe 的文件夹。

  11. 测试是否可以使用浏览器从客户端计算机访问服务。

  12. 在客户端计算机上,启动 ComCalcClient.vbs。

运行示例后进行清理

出于安全考虑,在完成示例后,请删除安装步骤中授予的虚拟目录定义和权限。