当用户注销时,COM+ 应用程序可能会在 Windows 中停止工作

本文提供了用户注销时 COM+ 应用程序在 Windows 中停止工作的问题的解决方案。

适用于:Windows Server 2019、Windows Server 2016、Windows Server 2012 R2、Windows 10 - 所有版本、Windows 7 Service Pack 1
原始 KB 编号: 2287297

症状

在 Windows 服务器上,你有一个 COM+ 服务器应用程序,其中标识配置为以特定用户身份运行。 工作一段时间后,应用程序可能会停止工作并持续失败。 必须重启 COM+ 应用程序才能解决此问题。

可能会在客户端计算机上的应用程序日志中看到类似于以下内容的错误。 如果客户端可执行文件与 COM+ 服务器应用程序在同一台计算机上运行,则会在 COM+ 服务器上看到此错误:

事件类型:错误
事件源:DCOM
事件类别:无
事件 ID:10006
日期: <DateTime>
时间: <DateTime>
用户:域\user
计算机:*****
说明:
尝试激活服务器时,DCOM 从计算机“servername”收到错误“未指定错误”:{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX}

在这种情况下,事件消息会告诉你,错误 (E_FAIL 或80004005或未指定的错误) 从服务器返回。 组件的 CLSID 将在事件日志条目中列出。

你还将在运行 COM+ 应用程序的计算机的应用程序日志中看到类似于以下内容的事件:

日志名称:应用程序
来源:Microsoft-Windows-User Profiles Service
日期: <DateTime>
事件 ID:1530
任务类别:无
级别:警告
关键字:经典
用户:SYSTEM
计算机:SERVERNAME
说明:
Windows 检测到注册表文件仍在被其他应用程序或服务使用。 文件将立即卸载。 之后,保存注册表文件的应用程序或服务可能无法正常运行。

详细-
从 \Registry\User\S-1-5-21-1049297961-3057247634-349289542-1004_Classes 泄露的 1 个用户注册表句柄:
进程 2428 (\Device\HarddiskVolume1\Windows\System32\dllhost.exe) 已打开密钥 \REGISTRY\USER\S-1-5-21-1123456789-3057247634-349289542-1004_CLASSES

你可能会看到创建组件实例的调用返回0x800703fa。

原因

首次初始化 COM+ 应用程序时,将登录与 COM+ 应用程序关联的用户标识。 如果此用户注销计算机,则会卸载该用户的配置文件,并且 COM+ 应用程序无法再读取用户标识配置文件中的注册表项。 从 Windows Vista 开始,用户配置文件服务将在用户注销时强制卸载用户配置文件。 在这种情况下,如果过程中未关闭注册表句柄,强制卸载用户配置文件的功能可能会中断应用程序。 此新的用户配置文件服务功能是默认行为。

解决方案

作为一种解决方法,可能需要修改用户配置文件服务的默认行为。 策略设置“ 在用户注销时不强制卸载用户注册表 ”会计数器 Vista 和较新的操作系统的默认行为。 启用后,用户配置文件服务不会强制卸载注册表,而是等待直到没有其他进程使用用户注册表,然后才能卸载注册表。 可以在组策略编辑器 (gpedit.msc) 中找到该策略。 “ 在用户注销时不强制卸载用户注册表 ”策略位于 “计算机配置>管理模板>系统>用户配置文件”下。

将设置从 “未配置” 更改为 “已启用” ,这会禁用新的用户配置文件服务功能。 DisableForceUnload 是添加到注册表的值。

更多信息

Windows 将始终卸载用户注册表,即使在用户注销时对每用户注册表项有任何打开的句柄也是如此。 使用此策略设置,管理员可以取消此行为,防止 Windows 在用户注销时强制卸载用户注册表。

注意

此策略只应用于由于此特定 Windows 行为而可能遇到应用程序兼容性问题的情况。 不建议默认启用此策略,因为它可能会阻止用户获取其漫游用户配置文件的更新版本。

如果启用此策略设置,Windows 不会在注销时强制卸载用户注册表,而是在关闭每用户注册表项的所有打开句柄时卸载注册表。

如果禁用或未配置此策略设置,Windows 将始终在注销时卸载用户注册表,即使用户注销时对每个用户注册表项有任何打开句柄也是如此。

即使启用了“ 在用户注销时不强制卸载用户注册表 ”策略设置,也可能记录事件 ID 1530 警告。 首次尝试卸载注册表配置单元后,将记录警告。 如果失败,将检查策略以确定是否应强制卸载注册表配置单元,而不考虑打开的注册表句柄。