在 vb.NET 中使用 COM+ 服务

查看原帖

2002-04-29 15:33 作者: 出处:Microsoft 责任编辑:
  摘要:将新的 Microsoft .NET 组件添加到现有的 COM 和 COM+ 应用 程序中,它们将协同工作;如果您需要开发能够参与事务、利用基于角色的 安全性或者与队列交互的 .NET 应用程序,这样做对您很有帮助。

  目标
  • 学习在 Microsoft? .NET 中使用 COM+ 服务。
  • 创建被服务的组件。
  • 部署被服务的组件。
  前提条件

  要彻底理解本文内容,需要满足以下条件:
  • 曾经使用过 Microsoft Transaction Server (MTS) 并在 Microsoft Visual Basic? 6.0 中分发过事务。
  • 曾经使用过 COM+ 服务中的基于角色的安全性。
  • 曾经在 COM+ 服务中创建和使用过队列。
  • 非常熟悉 .NET 类。
  • 能够在 .NET 中熟练创建控制台应用程序。
  在 .NET 中使用 COM+ 服务

  您可能曾经使用 COM+ 应用程序来托管使用 Visual Basic 或 C++ 编写的组件。COM+ 提供了许多有价值的服务,例如事务处理、排队组件、实时激活、基于角色的安全性、共享属性等。使用 COM+ 托管组件的一个主要优点在于:不必编写任何代码,就可以更改组件的行为方式,例如将组件的事务支持设置为“需要”。通过在组件服务 MMC 管理单元中,在 COM+ 组件上设置单选按钮,每次创建组件时,都将在 COM+ 事务的上下文中创建相应的组件。当组件使用 COM+ 事务时,所有数据库事务都由分布式事务处理协调器 (DTC) 处理。图 1 显示了在组件服务界面中设置“需要”事务选项的一个示例。

图 1:需要事务的 COM+ 组件示例

  设置组件安全性与设置事务支持一样简单。使用 COM+ 服务管理单元,您不用重新编译代码就可以决定哪个用户可以运行哪个组件,甚至哪个方法。

NET 可以使用所有 COM+ 服务


  在 .NET 框架中,只要您的类是从 System.EnterpriseServices.ServicedComponent 类派生的,就可以继续使用 COM+ 提供的所有服务。任何从 ServicedComponent 类派生的类都由 COM+ 服务托管,并且可以使用所有可用的 COM+ 服务。表 1 列出了 .NET 中支持的全部 COM+ 服务以及每个服务的简短说明。

表 1:可用的 COM+ 服务

COM+ 服务 说明
自动事务处理 应用声明事务处理功能
COM 事务处理集成器 (COMTI) 将 CICS 和 IMS 应用程序封装到自动化对象中
补偿资源管理器 (CRM) 对非事务性资源应用原子性和持久性属性
实时激活 通过方法调用激活对象,并在调用返回时停用此对象
松散耦合的事件 管理基于对象的事件
对象构造 在构造实例时向类实例传递持久字符串值
对象池 提供现成对象的池
排队组件 提供异步消息队列
基于角色的安全 基于角色应用安全权限
共享属性 在服务器进程中的多个对象之间共享状态
同步(活动) 管理并发
XA 互操作性 支持 X/Open 事务处理模型


  在 .NET 中使用 COM+ 服务的原因

  如果要编写能够参与事务、利用基于角色的安全性或者与队列交互作用的 .NET 应用程序,就会用到 .NET 中提供的 COM+ 服务。正如您将在本文中了解到的,.NET 使这些服务很容易实现。

提示:如果 .NET 代码无需与 COM+ 服务一起工作,也就是说,您只在 .NET 框架中工作,那么请不要使用 System.EnterpriseServices,否则会造成性能下降。

COM+ 组件开发概述

  在 .NET 中创建与 COM+ 服务交互的组件时,需要执行以下步骤。表 2 包含对各个步骤的说明。

  1. 创建类库。
  2. 创建所有类,使它们继承 System.EnterpriseServices.ServicedComponents 类。
  3. 创建程序集。
  4. 创建强名称。

    表 2:创建 .NET 组件时使用的术语定义

    术语 说明
    类库 包含类的 .dll 项目类型,此类项目通常没有用户界面
    System.EnterpriseServices.ServicedComponents .NET 框架中的一个类,使用它才能与 COM+ 服务进行交互
    程序集 对项目中所有类和接口的描述
    强名称 从程序集生成 GUID,以便可以使用 COM+ 服务注册组件

  开发基于事务的组件

  在本文的第一部分,您将学习如何创建使用 COM+ 的事务性服务的 .NET 组件,还将学习如何编写组件以及与此组件交互的前端应用程序。

  创建 COM+ 事务组件

  要使 .NET 组件能够在 COM+ 服务下运行,需要执行以下步骤。首先,必须创建一个从 System.EnterpriseServices.ServicedComponent 类派生的类。这个基类提供了与 COM+ 服务交互所需的所有适当方法和属性。需要将该类标记为需要新事务,并将所创建的任何方法标记为在没有错误出现的情况下可以自动完成事务处理。下面是具体操作。

  1. 打开 Microsoft Visual Studio? .NET,创建一个新的 ClassLibrary 类型的项目。
  2. 将 Class1.vb 文件重命名为 COMPlusServices.vb。
  3. 打开 COMPlusServices.vb 文件,将类名 Class1 更改为 COMPlusServices
  4. 在此新类中键入如下所示的代码:

    Imports System.EnterpriseServices
    Imports System.Reflection
    '********************************************
    ' COM+ 注册详细信息
    ' 提供 COM+ 应用程序名
    <Assembly: ApplicationNameAttribute("ComPlusExample")> ' 提供具有强名称的程序集
    <Assembly: _
    AssemblyKeyFileAttribute("bin/ComPlusExample.snk")>
    '******************************************** <TransactionAttribute(TransactionOption.Required)> _
    Public Class COMPlusServices
      Inherits ServicedComponent
      Public Sub New()
        MyBase.New()
      End Sub
      <AutoComplete()> Public Function DoTransaction() _
      As String
        Return "COM+ 成功"
      End Function
    End Class

    此代码以导入多个名称空间开始,从而在声明组件时省略了一些键入内容。
  5. 接下来是 COM+ 注册详细信息。请输入以下代码行:

    ' 提供 COM+ 应用程序名
    <Assembly: ApplicationNameAttribute("ComPlusExample")>

  此行指定 ApplicationNameAttribute 的值为 ComPlusExample。这是在 COM+ 目录中注册该 COM+ 应用程序时要使用的名称。第一次调用此组件后,当打开 MMC 管理单元的 COM+ 应用程序文件夹时,您会发现应用程序名称就是这个名称。

  接下来的代码声明 AssemblyKeyFileAttribute 属性:

<Assembly: _
AssemblyKeyFileAttribute("bin/ComPlusExample.snk")>

  此属性通知 COM+ 目录有关强名称的信息所在的位置。在后面的步骤中,将创建用于描述 COM+ 组件的 .SNK 文件。

  最后,使用以下代码声明类名 COMPlusServices:

<TransactionAttribute(TransactionOption.Required)> _
Public Public Class COMPlusServices


  此类名前面的属性通知 COM+,您要将事务属性设置为“需要”。添加此行代码相当于打开 COM+ 应用程序管理单元(如图 1 所示)并手动设置此属性。

  该类中的下一行代码继承 System.EnterpriseServices 名称空间中的 ServicedComponent。

Inherits ServicedComponent

  如果不包含此行,将无法使此组件在 COM+ 下运行。

   添加事务方法

  现在,类已经设置完毕,可以创建真正能够实现某些功能的方法了。在您编写的代码中,DoTransaction 函数返回一个字符串值,但它只给出了您必须使用的语法,如果不使用此语法该方法将无法参与事务。

<AutoComplete()> Public Function DoTransaction() As String
Return "COM+ 成功"
End Function


  在此方法前面加上 <AutoComplete()> 属性很重要。这表示只要此方法中没有出现异常,当它结束时就会自动调用 SetComplete。如果该方法中存在异常,则 .NET 运行时将自动调用 SetAbort 方法。这与在 Visual Basic 6.0 中编写 COM 组件不同,在 Visual Basic 6.0 中,必须手动显式调用 SetComplete 和 SetAbort。

  创建强名称

  在编译组件之前,您需要为此组件的程序集指定一个强名称。如果不指定,COM+ 目录将不能识别该组件,也就无法注册它。实际上,您已经通过前面使用的 AssemblyKeyFile 属性指定了强名称,现在需要使用强名称工具 (Sn.exe) 创建强名称并使 GUID 与程序集关联。
  1. 打开命令提示。
  2. 要创建强名称,请在命令提示下键入以下代码,然后按 Enter 键。

    sn -k ComPlusExample.snk
  3. 将 ComPlusExample.snk 文件从硬盘驱动器的根目录(通常为 C:/)复制到项目所在文件夹的 bin 目录下。

  现在,需要编译此程序,使它能生成在 COM+ 注册此组件必需的文件。在 Visual Studio .NET 中,在 Build(生成)菜单上,单击 Build(生成)。

生成客户端测试应用程序

  现在,组件生成完毕,需要生成客户端应用程序来调用并测试此组件。创建简单的控制台应用程序,此程序中的模块文件的 Main 方法创建新组件实例,并调用 DoTransaction() 方法。以下是主要步骤:

  1. 在 Visual Basic .NET 中,创建新的控制台应用程序项目。
  2. 添加对刚创建的组件的引用。
  3. 键入如下所示的代码。

    Module modMain
      Sub Main()
        Dim objCOMPlus As New _
        COMPlusJumpStart.COMPlusServices()
        Console.WriteLine(objCOMPlus.DoTransaction)
        Console.ReadLine()
      End Sub
    End Module

  试一试

  最后,运行此程序并查看其运行情况。

  1. 打开组件服务 MMC 管理单元,验证您的组件已经动态注册到 COM+ 目录中。您应该看到图 2 所示的界面。
  2. 编译并运行控制台应用程序。

    图 2:COM+ 目录中的新建 .NET 服务组件

  基于角色的安全

  如果多个用户调用在 COM+ 下运行的 COM 组件,您需要进行验证,只允许特定用户访问某个组件。COM+ 允许您定义角色并为其分配 NT 用户。定义并设置角色后,就可以指定哪些角色可以运行哪些组件,甚至指定可以运行组件上的哪些方法。

  请在此 COMPlusServices 类中添加一个方法,以添加基于角色的安全性。您需要创建名为 Managers 的角色,并在新方法中进行测试,查看调用者是否为 Managers 角色。  添加基于角色的安全性的步骤

  不用直接从组件服务 MMC 管理单元修改 COM+ 应用程序来添加安全角色,只需在项目中添加一个新属性。使用 SecurityRoleAttribute 类添加新的 Managers 角色。这个类的构造函数有两个参数:role(字符串值)和 everyone(布尔值)。role 参数指定要创建的角色的名称,everyone 参数指定是否将内置 Everyone 组添加到此角色的用户中。

  1. 在注释“COM+ 注册详细信息”下键入以下代码,将新的安全性角色添加到 COM+ 应用程序中。

    '********************************************
    ' COM+ 注册详细信息

    ' 基于角色的安全性属性
    <Assembly: SecurityRoleAttribute("Managers",False)>
  2. 更改安全级别设置,以便在进程级和组件级执行访问检查。这使 COM+ 应用程序具有安全性调用上下文。
  3. 显示 COM+ 服务管理单元。
  4. 单击 Security(安全性)选项卡并更改安全级别,如图 3 所示。

    图 3:在 COM+ 目录中设置安全级别属性

  除了手动进行处理外,还可以在组件中添加属性,通知组件执行访问级别检查。以下是在 COMPlusServices 类一开始的“COM+ 注册详细信息”部分添加的代码。

<Assembly: ApplicationAccessControlAttribute
(AccessChecksLevel:=AccessChecksLevelOption.ApplicationComponent)>

检查安全性角色

  现在,将新方法添加到名为 IsManager 的类中。此方法将检查用户是否为具有 Managers 角色的成员。此方法是一个函数,它返回一个布尔值,表明调用者是否为 Managers 角色。要访问调用该方法的用户的安全上下文,需要使用 SecurityCallContext 类。通过调用 CurrrentCall 方法,获得当前用户的上下文。然后调用 IsCallerInRole 方法,并传递 Managers 作为此角色的名称。

  1、将以下方法添加到 COMPlusServices 类中。

Public Function IsManager() As Boolean
  Dim objCallContext As SecurityCallContext = _
  SecurityCallContext.CurrentCall
  IsManager = _
  objCallContext.IsCallerInRole("Managers")
End Function

  现在,需要重新生成该组件以测试此新方法。

  2、从 Visual Studio .NET 的 Build(生成)菜单中,单击 Rebuild Solution(重新生成解决方案)。

  试一试
  • 修改控制台客户端应用程序的 Sub Main() 方法中的代码。此代码应如下所示:

    Sub Main()
    Dim objCOMPlus As New _
      COMPlusJumpStart.COMPlusServices()
      Console.WriteLine(objCOMPlus.DoTransaction)
      Console.WriteLine(objCOMPlus.IsManager().ToString)
      Console.ReadLine()
    End Sub

      2、在命令提示下键入您编译的可执行文件的名称,运行控制台应用程序。

      第一次运行该代码时会发生异常,并说明访问被拒绝的原因是 Managers 角色中没有添加任何用户。要纠正这个异常,请将您自己添加为 Managers 中的用户,并再次运行该应用程序。这次应该不会出现任何异常。也可以在代码中添加异常处理。以下是添加了异常处理代码的客户端应用程序示例:

    Sub Main()
    Try Dim objCOMPlus As New _
      COMPlusJumpStart.COMPlusServices()
      Console.WriteLine(objCOMPlus.DoTransaction)
      Console.WriteLine(objCOMPlus.IsManager().ToString)
      Console.ReadLine()
    Catch objException As Exception
      Console.WriteLine("出现错误。 " _
      & "详细信息: " _
      & objException.Message)
      Console.ReadLine()
    End Try
    End Sub

      使用排队组件

      在 COM+ 应用程序中,添加排队支持很简单。只需确保该应用程序作为服务器程序运行(进程外),然后在选项卡上设置 Queued(排队)和 Listen(侦听)属性。完成这些设置后,客户端应用程序就可以异步或同步调用组件。该功能的精妙之处在于,不必更改 COM 对象中的代码,只需在 COM+ 目录中更改其属性。

      .NET 框架支持排队组件,而且,正如您期望的那样,您可以通过使用属性,而不用手动更改 COM+ 目录即可为组件提供排队支持。

      请在 COMPlusServices 类中添加一个方法,然后在 .NET 客户端应用程序中使用 COM+ 排队组件服务异步调用它。 将 COM+ 应用程序作为服务器程序(进程外)。这是排队组件的要求。要使用属性达到此目的,请将以下代码添加到项目中:

    '********************************************
    ' COM+ 注册详细信息
    <Assembly: ApplicationActivationAttribute(ActivationOption.Server)>

      在组件中添加排队支持。使组件可访问 MSMQ 队列,并使其侦听自己的队列以处理消息。下面是使用属性完成此过程的代码:

    '********************************************
    ' COM+ 注册详细信息
    <Assembly: ApplicationQueuingAttribute(Enabled:=True,
     QueueListenerEnabled:=True)>

      在类 QueueTest 中添加一个方法。确保它是子例程且不返回任何值。使用它在 Windows 应用程序日志中写入信息。此代码应如下所示:

      Public Sub QueueTest()
        System.Diagnostics.EventLog.WriteEntry(_
        "COMPlusServces","队列测试",_
        Diagnostics.EventLogEntryType.Error)
      End Sub

      就到这里吧。这就是为使组件成为 COM+ 排队组件需要完成的全部操作。

      试一试

      现在,应该通过创建另一个控制台应用程序并调用此组件,来尝试运行该排队组件。
  • 创建新的控制台应用程序。
  • 将以下代码添加到控制台应用程序的 Sub Main 过程中。

      Sub Main()
        Dim objTest As COMPlusJumpStart.COMPlusServices
        Dim strMoniker
        strMoniker = _
        "queue:/new:COMPlusJumpStart.COMPlusServices"
        objTest = GetObject(strMoniker)
        objTest.QueueTest()
      End Sub

      它将异步调用组件中的 QueueTest 方法。如果要同步调用此方法,可以象调用该组件中的所有其他方法一样调用它。

      现在,可以运行此控制台应用程序,尝试运行此排队组件。

      自 Visual Basic 6.0 以来 COM+ 的变化

      您已经通过 Visual Basic 6.0 或 COM 了解了 .NET 中的许多内容。现在,您已经获得了在 .NET 框架中工作的好处,这有助于实现对象的平稳交互,您只需编写少量代码,执行少量维护即可。

      这类简化操作中最典型的是,在 Visual Basic 6.0 中,必须手动显式调用 SetComplete 和 SetAbort。而在 .NET 中,SetComplete 和 SetAbort 由 <AutoComplete()> 属性调用。

      Visual Basic .NET 和 Visual Basic 6.0 的另一个不同之处是,由于使用单线程单元线程模型,Visual Basic 6.0 组件不能使用 COM+ 对象池。而 Visual Basic .NET 组件是 .NET 组件,支持任何单元线程模型,所以可以使用 COM+ 对象池。

      总结  可以看出,利用 .NET 框架可以方便地利用 COM+ 提供的服务。这意味着您可以将新的 .NET 组件添加到使用 COM 和 COM+ 编写的现有程序中,而且它们可以协同工作。这一点非常重要,因为这意味着您不必放弃现有的全部 COM 和 COM+ 代码。如果您从头开始生成新应用程序,强烈建议您完全在 .NET 框架中生成它,因为这样效率会更高。
  • 版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

    相关推荐


    Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
    VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
    在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
    转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
    Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
      窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
      Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
    ‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
    Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
    VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
    今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
    在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
    注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
    Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
      PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
      沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
    Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
    Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
    以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
    Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")