信息: COM 服务器激活和 NT Windows 站

文章翻译 文章翻译
文章编号: 169321 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

当客户端请求一个已注册的类的类对象时,COM 返回现有的类对象,或启动一个注册为包含所请求的类对象的过程。发出请求的客户端 (无论会导致进程创建或 $"启动") 用于获取类的对象引用的过程称为"激活。

在特定的条件下 COM 可能会启动一个新的服务器进程,即使在已有的类对象正在运行,并且已被注册为多个使用。 此外,COM 创建一个新的进程时在该过程即可启动中称为"窗口站"在新的安全环境而不是共享一个现有的窗口站,如交互式窗口工作站。(上窗口站的详细信息,搜索该短语的 Win32 SDK 文档。

由于某些原因,了解一个激活请求过程中创建新的进程和窗口站的 COM 的算法非常重要。 第一次,COM 可能创建多个使用类对象的多个进程的实例,因为安全问题。第二个,始终将在单独的进程中启动一次使用服务器,但它们可能也可能不会启动单独的窗口站。这种差异可能表现为应用程序代码,例如两个 COM 服务器尝试通过窗口消息或安全通讯功能 (如 COM 或 RPC 进行通信时某些异常情况下。第三个,因为窗口站同时可以在 Windows NT 中创建的数量是有限的它是必要知道何时您的 COM 服务器获取新的窗口站时。

本文分析不同激活方案,并解释了何时创建新的进程和窗口站。

更多信息

当 COM 创建一个新的服务器进程,或将新的窗口站指派给新的服务器进程取决于几个因素:
  1. 在其下 COM 类被设置为启动安全标识。类标识可通过 dcomcnfg 命令工具进行设置,以及由名为 value 的类的 AppID 项在 RunAs 指定。
  2. 单个使用与多个使用注册的类对象。
  3. 客户端进程 (这是数值类型的值,该值代表特定用户帐户/安全标识/主体在 Windows NT 环境中) 的安全 Identifier(SID)。
  4. 登录标识符 (LUID) 到的客户端进程 (为每个唯一登录到运行 Windows NT 的计算机生成一个新的登录标识符。此登录可能是通过在用户名和密码在 NT 登录提示,中键入用户或通过调用 win32 API LogonUser)。
  5. 本地和远程激活。
  6. 客户端的窗口站。

多个使用类

多个使用类是用 REGCLS_MULTIPLEUSE 标志指定 (通过 CoRegisterClassObject() API) 的 COM 注册的类。这样一个类的 COM 通常使用服务器进程一个的实例,所有的客户端激活请求。但是,配置为在安全的启动用户和在几个其他情况下下运行的类的 COM 启动服务器进程为激活请求提供服务的新实例。因此启动服务器进程的一个新实例,时就可能在服务器进程获取一个新的窗口站。我们将分析下面,在各种方案,但第一次我们将讨论简要为什么 COM 启动时类对象的实例已被注册为一个多易用类包含所请求的类对象的新进程。

第一个当 COM 类 (更准确地时的 AppID 与 COM 类相关联) 注册"启动用户"作为运行系统与系统管理员已经设置了特定的安全策略到该类。该策略是一个激活器应接收类对象内激活代码相同的安全上下文中运行的进程。

此安全策略可以会服务器定义的所有激活请求 (如由 REGCLS_MULTIPLEUSE) 只有一个类工厂对象行为的发生冲突。COM 使安全策略的优先级高于应用程序的行为。如此一来注册到"启动用户"作为运行的多个使用服务器将不行为取决的多个使用一般的规则。对于每个激活的安全主体,将会启动一个新的进程。

第二个,不由 COM 运行在不同于为给定的 CLSID 指定安全上下文中启动一个过程将该 CLSID,该注册将 fail(CoRegisterClassObject will return an error code CO_E_WRONG_SERVER_IDENTITY in this case)。如果以后到达的激活请求一个新的进程将会启动由 COM 使用 CLSID/appid 为指定的安全上下文。COM 无法再信任代码调用 CoRegisterClassObject() (不安全的操作),它可以只信任 (注册表是安全的数据库) 的注册表设置,以确定要使用以及如何运行它的类对象。此行为可防止未经授权的用户的类对象的计算机范围欺骗的非法。

与该记住我们现在返回到该问题的新进程和窗口站创建时时多使用服务器时启动的 com。 请注意客户端的 LUID 无关紧要以任何方式在最多使用类的情况下。
  1. "交互式用户"安全身份。 在多个使用 COM 类的 AppID 配置为以交互式用户"身份运行的位置的该情况下将使用第一次的服务器进程和其类对象由 COM 为所有后续的激活请求提供服务。此服务器实例会将交互窗口工作站,如果存在 (如果用户不在本地登录然后所有的激活请求将失败)。 如上所述,如果由 COM 不启动某个进程并不运行在交互式窗口站注册 CLSID,该注册将会失败。如果以后到达的激活请求,将与交互式用户的安全上下文启动一个新的进程。此行为可防止非法欺骗的类对象。 由于没有额外的服务器进程以往任何时候都由 COM 启动,新窗口站这一问题是 moot。客户端的 SID,其 LUID 或它是本地还是远程无关紧要在这种情况下。
  2. 此用户的安全标识。 如果多个使用 COM 类的 AppID 配置同样,以此用户身份运行 (一个预定义的安全 ID),第一个服务器处理和它的类对象将由 COM 使用为所有后续的激活请求提供服务。此第一个服务器实例将有其自身作为第一个过程创建的一部分创建的窗口站。由于没有额外的服务器进程以往任何时候都由 COM 启动,附加窗口站这一问题是 moot。客户端的 SID,其 LUID 或它是本地还是远程无关紧要在这种情况下。 请注意当您启动的类/appid 配置为作为"该用户,运行,即使在同一个用户当前登录交互式 winstation 第一个实例时,将会创建一个新的窗口站。COM 从不使用交互式 winstation 进行启动配置此用户的身份运行,因为这样会导致不同的行为取决于不相关的问题的当前登录用户的标识类的一个服务器。 如上所述,如果由 COM 不启动某个进程并不在指定此用户在该帐户下运行试图注册该 CLSID 注册会发生故障和 $ 如果更高版本的激活请求到达时的一个新的进程将在此用户帐户启动。此行为可防止非法欺骗的类对象。 在另一方面,如果过程注册为给定的 CLSID/APPID 被配置为此用户运行中, 创建适当的用户帐户由 COM 以外的其他一些代理 (例如对于它运行的交互式用户交互式用户是相同用户作为该用户或启动时通过 CreateProcess() 作为此用户在同一安全上下文中运行服务时),然后注册其 REGCLS_MULTIPLEUSE 类对象,COM 将使用现有的正在运行的类对象,来满足来自任何客户端的后续传入激活请求。
  3. "启动用户"的安全标识。 在本例中类的 AppID 设置 (这也是一个"作为激活器激活"类) 的"启动用户"idenitity 下启动。 a.本地客户端。 首先考虑本地计算机的这种情况。有两个规则: 1 每个不同的激活客户端 SID 将导致 COM 启动服务器进程,即使在同一窗口站的新实例。 2.甚至匹配的 sid (如大小写的同一个用户登录不止一次到 NT 单机),每个不同的本地客户端窗口站将导致 COM 启动服务器进程的一个新实例。 也就启动用户标识多使用服务器是永远不会在整个共享窗口站的。具有相同的 SID 和相同的窗口站的所有客户端进程将共享相同的窗口站在单个服务器进程。由于服务器共享的客户端将窗口站会不创建任何新的窗口站。 例如对于假定您以交互方式登录为 a_domain\a_user。运行客户端都将连接到服务器 (具有交互式窗口工作站) 的同一实例的多个实例。现在让我们假设您有客户端,这是一个服务设置为启动 a_domain\a_user 下启动。此服务将启动 COM 服务器的新实例。发生这种情况是因为 COM 将导致要启动由于服务进程窗口站非交互式窗口工作站中--即使 service(client) 进程的标识是标识正在运行的服务器进程 (a_domain\a_user) 的相同服务器的新实例。但是,请注意 COM 服务器进程的创建任何新的窗口站。服务器仍将继承服务的该窗口站。如果该服务设置为本地系统下启动,并与桌面交互 (服务中的"允许服务以与桌面交互]"复选框,请参阅在 $ 控制面板中的小程序),然后在交互式窗口站或 winsta0 将运行服务。在这种情况下 COM 仍将启动新实例的服务器 (它是本地系统的客户端的 SID 在这种情况下是不同的服务器的 SID,这是 a_domain\a_user) 在交互式窗口站。 b.远程客户端。 在远程的激活的情况下 COM 忽略窗口站,客户端的因为客户端是远程,与本地上述情况不同。 下面的规则是每个新的客户端 SID 将导致服务器进程来启动的新实例,每个新的服务器进程将获得新的窗口站。后续的激活请求远程客户端具有相同的 SID 将重用现有的类对象,以及其进程和窗口站已注册。例如对于假定您登录为 a_domain\a_user 10 个不同的计算机上。 所有这些计算机从客户端将连接到服务器计算机上服务器的同一个实例。从 a_domain\b_user 机器的客户端将启动一个新的服务器实例和新的窗口站。 具有相同 SID 已启动请求的 CLSID 为注册的 COM 服务器的本地用户身份的远程调用方将重新使用现有的类对象。但是,启动 COM 服务器时的顺序在这种情况下很重要。如果服务器第一次启动本地客户端,远程客户端具有相同 SID 将连接到此服务器。另一方面,如果服务器第一次启动远程客户端,具有相同 SID 的本地客户端将启动该服务器的新实例。这返回上面提到的窗口站规则。对于本地的客户端的客户端和服务器在窗口站为远程客户端将被忽略的客户端将窗口站必须与相匹配。例如对于本地客户端 a_domain\a_user 第一次启动服务器,如果远程客户端 a_domain\a_user 将到服务器连接。相反,如果远程客户端 a_domain\a_user 第一次启动服务器,然后本地客户端 a_domain\a_user 将启动一个新的服务器实例和新的窗口站。 客户端的 LUID 在这种情况下并不重要。
  4. 基于服务的 COM 服务器。 一个 COM 类/appid 封装在 Win32 服务的是按实际需要多使用服务器,因为可一次启动服务。在这种情况下在第一次激活请求一个新的进程将在其自己的窗口站中启动。有两个例外: 如果该服务设置为在本地系统帐户下启动,它将继承系统预定义的窗口站 a.。 b.如果该服务设置为在本地系统帐户下启动,并且可以与桌面交互,它将继承交互式窗口站或 winsta0。所有的后续的激活请求是否本地或远程,由处理服务的类对象。 如上所述,如果由未启动一进程 COM 和未运行时指定的服务将该 CLSID,该注册将失败,并且如果更高版本的激活请求到达时的已注册的服务都将会启动。此行为可防止非法欺骗的类对象。

单个使用类

注: 单使用类应避免使用尽可能多地。使用一次性注册是旧式设置,旨在支持较旧的 COM 应用程序,并减轻传统 com。 非 COM 应用程序的移植 强烈建议新的类被设计为支持多个使用类对象注册。这是在具有此用户"身份的服务器的情况下尤其如此单个使用类会导致正好相反的多用途的类的效果。他们创建一个新的服务器进程和每激活新窗口站,我们讨论下面,这可能导致在 Windows NT 资源问题。

使用一次性类是一个使用 REGCLS_SINGLEUSE 标志指定 (通过 CoRegisterClassObject() API) COM 注册。这样一个类的 COM 将始终启动新实例的类的服务器进程,为每个激活请求来自任何客户端 (本地或远程)。为了本文的其余的问题是: 当服务器将获得一个新的窗口站?
  1. "交互式用户"安全身份。 采用这种情况在其中使用一次性类设置为通过其 AppID 交互式用户"标识下启动。对于这种情况下服务器进程的每个新实例将始终共享在交互式窗口工作站,如果存在 (如果用户不在本地登录然后所有的激活请求将失败)。没有新的窗口站将创建由 com。
  2. 此用户的安全标识。 现在考虑一下这种情况使用一次性 COM 类的 AppId 设置为此用户"标识下运行的位置。在这种情况下,规则是非常简单。每个新的客户端激活启动新的进程中新的窗口站。这是不论是否指定为此用户"用户登录到交互式窗口站的激活请求的任何时候,则返回 true。
  3. "启动用户"的安全标识。 a.本地客户端。 在本地计算机激活的情况下,服务器进程将始终获得窗口站,客户端。没有新的窗口站是以前创建的。例如对于假定您以交互方式登录 a_domain\a_user 和您运行的客户端程序的多个实例。每个新的生成实例的服务器将获得交互式窗口工作站。现在,假设客户端是一种服务,本地系统帐户下运行。在这种情况下,COM 服务器将共享服务进程的窗口站。 b.远程客户端。 在远程激活情况下 COM 忽略窗口站,客户端的因为将远程客户端。与往常一样将启动一个新的服务器实例进程的每个远程激活。规则是: 1 对于每个新远程客户端 SID,将创建一个新的窗口站服务器进程的。 2.为每个新远程客户端 LUID,将服务器进程的创建新的窗口站。 3.所有具有相同的 SID/LUID 对的远程客户端将创建共享相同的窗口站的服务器。 例如对于您登录到远程客户端计算机上作为 a_domain\a_user。此客户端启动远程服务器将获取新的窗口站。现在,a_domain\a_user 启动客户端应用程序的第二个实例在相同的客户机上,这需要依次启动远程计算机上服务器的新副本,如果此服务器将共享原始服务器的窗口站。现在假定您登录到再次与 a_domain\a_user 的另一台计算机,并从那里运行客户端。相应的服务器实例将具有新的窗口站。此示例演示即使客户端 sid 是在相同由于第二个客户端具有不同的 LUID,其服务器进程将获得新的窗口站。
  4. 基于服务的 COM 服务器。 使用一次性类应永远不会作为 Windows NT 服务。 因为它可能无法运行 Windows NT 服务进程的多个实例,那么就没有必要中。

表汇总的方案

---------------------------------------------------------------------------
       |                      Multiple-Use Server
       |             (class factory has requested reuse)
       |                       Activation Modes
       |-------------------------------------------------------------------
       |   Interactive     | As "This       |As "Launching    | Win32
Client |      User         |   User"        |   user"         | service
				
Local  | Process launched  | Process        | Process         | Service
       | in the            | launched in a  | launched client | started on
       | interactive window| new window     | window station  | first
       | station on first  | station on     | on first        | activation
       | activation        | first          | request,        | request
       | request,          | activation     | subsequent      | (new winsta
       | subsequent        | request,       | requests from   | or system/ 
       | requests get      | subsequent     | the same SID/   | interactive
       | existing class    | requests get   | window station  | winsta
       | object,           | existing class | get existing    | depending
       | activations fail  | object         | class object, no| on service
       | if no user logged |                | sharing of class| config),
       | on locally        |                | objects across  | subsequent
       |                   |                | window stations | requests
       |                   |                | even if same SID| get
-------|                   |                |-----------------| existing
Remote |                   |                | Process launched| class
       |                   |                | in new winsta on| objects
       |                   |                | first activation|
       |                   |                | request by a    |
       |                   |                | SID, subsequent |
       |                   |                | remote requests |
       |                   |                | by the same SID |
       |                   |                | get existing    |
       |                   |                | class object;   |
       |                   |                | class launched  |
       |                   |                | by local user   |
       |                   |                | reused by remote|
       |                   |                | callers with    |
       |                   |                | same SID        |
				
---------------------------------------------------------------------------

---------------------------------------------------------------------------
       |                      Single-Use Server
       |          (new process created for each activation request)
       |                       Activation Modes
       |-------------------------------------------------------------------
       |   Interactive     | As "This       |As "Launching    | Win32
Client |      User         |   User"        |   user"         | service
				
Local  | Process always    | Process always | Process always  | N/A(only
       | launched in the   | launched in a  | launched in     | one
       | interactive       | new window     | the window      | activation
       | window station,   | station        | station of      | possible)
       | if no interactive |                | client process  |
       | window station    |                |                 |
       | activation fails  |                |                 |
-------|                   |                |-----------------|
Remote |                   |                | if both SID and |
       |                   |                | LUID of the     |
       |                   |                | client match    |
       |                   |                | previous client |
       |                   |                | activation,     |
       |                   |                | process launched|
       |                   |                | in existing     |
       |                   |                | window station, |
       |                   |                | otherwise in new|
       |                   |                | windowstation   |
				
---------------------------------------------------------------------------

窗口站和 Windows NT 资源

此部分中,我们将分析创建 Windows 2000 及如何,应该会影响您的 COM 服务器的配置下的新窗口站的含义。将看到是窗口站可创建一个 Windows NT 的计算机上的数量限制。当超出该限制,了自动允许 Windows NT 将会失败 COM 试图启动服务器进程的一个新实例。通常,则会显示一条错误消息如下所示:
动态链接库的初始化
d:\winnt\system32\kernel32.dll 失败。在过程
异常终止。
在 Windows NT 下每个窗口站已至少一个与之相关联的桌面。Windows NT 的台式机上运行的所有窗口应用程序使用特殊的内存堆。默认状态下,每个桌面堆消耗 3 MB 的内存。 Windows NT 的不可配置限制为 48mb 用于创建桌面堆。 这意味着可以在 Windows NT 的计算机创建的窗口站的最大数目为 16 (可能是较少因为窗口站可包含多个桌面)。若要增加此数字,可以通过编辑注册表使用注册表编辑器来减少默认桌面堆大小。

警告: 不正确地使用注册表编辑器可以会导致严重的系统问题,可能需要重新安装 Windows NT 才能解决问题。 Microsoft 不能保证可以解决任何问题,从而从使用注册表编辑器。使用此工具需要您自担风险。

指定您需要编辑的值将出现在以下项:
   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
   Manager\SubSystems
				
您需要编辑"窗口"指名值。它是一个 REG_SZ 的字符串。编辑字符串和查找"共享节 = 1024 3072"。修改此读取"共享节 = 1024,3072 512"。您需要重新启动计算机使此更改才能生效。通过此更改指定为交互式窗口站的桌面的 3 MB (默认) 堆大小和 512 KB 的所有非交互式桌面 (第一个参数已过时,但不是应更改)。此更改将允许创建的大约小于 48mb/512 KB 或 96 窗口站。

注: 一个窗口站可包含在其中的多个桌面。在上面提到的本地客户端进程与窗口站的位置"启动用户"服务器的讨论,应被认为是对窗口站和桌面上的较短的窗体。"启动用户"设置实际上用于旧式非 DCOM 支持服务器,应很少使用。 这类旧版服务器预期在他们自己的台式计算机中运行。因此,对于 MULTIPLEUSE"启动用户"服务器,相同的窗口站内的不同桌面中的每个客户端进程会导致在该窗口站/桌面中启动新的服务器进程。对于"启动用户"SINGLEUSE 服务器,再次,服务器继承窗口站/桌面的客户端进程。

在 Windows NT 4.0 服务包 4.0 COM 将尝试重新使用窗口站。之前对此,如果服务器被设置为 RunAs 特定用户和服务器进程的多个实例启动,如果每个进程将获取它自己的窗口站。这将导致以上描述的限制的窗口站。在 SP4,COM 将试图创建所有被设置为同一用户标识 (或标记) 下运行在同一窗口站 RunAs (也就是不"作为激活"或"启动用户") 服务器。

这不需要调整桌面堆大小在这种情况下,使用相同的令牌运行多个服务器进程的位置。如果您的配置中的所有服务器都设置为 RunAs 为同一用户或运行在同一 RunAs 服务器进程的多个实例,然后应不减少桌子顶部 heapsize,按本文中的建议。建议为默认值 (3 M) 中在这种情况下将其保留。这是因为,如果您降低桌面堆,然后在系统可以在创建多个窗口站/桌面 ; 但是,可以在一个窗口站/桌面中运行的进程数会逐渐变小。

另一方面,在您的配置中如果您有多个具有不同的令牌运行的服务器然后您将面临窗口站限制。在这种情况下,您应该遵循减小桌面堆大小的文章中建议。

参考

桌面堆问题有关的其他信息,请参阅 Microsoft 知识库中下面的文章:

142676如何更正常见 User32.dll 文件错误

属性

文章编号: 169321 - 最后修改: 2005年7月11日 - 修订: 2.5
这篇文章中的信息适用于:
  • Microsoft OLE 4.0?当用于
    • Microsoft Platform Software Development Kit-January 2000 Edition
关键字:?
kbmt kbapi kbdcom kbenv kbinfo kbinterop kbkernbase kbprogramming kbusage KB169321 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 169321
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com