由非托管 (C++) COM 服务器实例化的托管 (C#) 控件在 Windows 更新后中断

Posted

技术标签:

【中文标题】由非托管 (C++) COM 服务器实例化的托管 (C#) 控件在 Windows 更新后中断【英文标题】:Managed (C#) control instantiated by unmanaged (C++) COM Server broken after Windows update 【发布时间】:2019-01-01 07:33:14 【问题描述】:

我开发了一个托管 (C#) 控件,将由非托管 (C++) COM 客户端使用。

由于我不能强制用户提升他们的权限(即使是安装),所以无法使用提升的(管理员)帐户注册控件,而必须由普通的非提升用户帐户注册。同样,非托管应用程序必须使用非提升的用户帐户运行。

因此,我设计了注册,以便在 HKEY_CURRENT_USER\Software\Classes\ (HKCU) 下添加注册表项。这些注册表项随后会被 Windows 视为 HKEY_CLASSES_ROOT (HKCR) 配置单元的一部分。

这多年来一直运行良好,但在上个月,我看到 Windows 7 Professional 在实例化此控件时已开始报告 E_CLASSNOTREGISTERED。

当注册到 HKEY_LOCAL_MACHINE\Software\Classes\ (HKLM) 时,即使来自 HKCR 的视图在两种情况下都是相同的,也可以实例化控件。

由此我只能得出结论,Windows 正在寻找 HKLM 为我的控件查找注册表信息,即使是从非提升的 COM 客户端 (?!)。

这是一种新行为,仅在安装了 Microsoft 最新软件补丁的 Windows 7 计算机上发生。未打补丁的机器按预期工作(即我可以在 HKCU 中注册时实例化我的控件)。

这是一个严重的问题。

有谁知道 MS 做了什么改变导致这个问题,有没有办法解决它?

谢谢!

【问题讨论】:

我只以两种方式使用过 COM:HKLM/HKCR 注册,或通过“并行”程序集 (docs.microsoft.com/en-us/windows/desktop/SbsCs/…)。第二条路径可以让你解决这个问题。基本上,您为您的程序创建一个指向本地私有(非管理员要求)COM 对象存储的 .NET 样式应用程序清单,并且 COM 管道在实例化 COM 工厂/COM 之前在 HKLM/HKCR 中查找之前查找那里目的。它从 Win2K 或 WinXP 时代就已经存在,但并不为人所知。 花了一些功夫,但这会奏效!我把传统的COM注册去掉了,换成Registration-Free COM Interop谢谢! 【参考方案1】:

考虑使用"side-by-side" assemblies。基本上,您为您的程序创建一个指向本地私有(非管理员要求)COM 对象存储的 .NET 样式应用程序清单,并且 COM 管道在实例化 COM 工厂/COM 之前在 HKLM/HKCR 中查找之前查找那里目的。它从 Win2K 或 WinXP 时代就已经存在,但并不为人所知。

【讨论】:

以上是关于由非托管 (C++) COM 服务器实例化的托管 (C#) 控件在 Windows 更新后中断的主要内容,如果未能解决你的问题,请参考以下文章

托管 BigQuery 实例

C# 中的非托管 C++ 类

在非托管 C++ 程序中实现 C# DLL COM 文件

使用 COM 互操作从非托管 C++ 访问 c# 属性

从非托管 c++ 调用托管 c# 函数

从非托管 c++ 调用托管 c# 函数