2

我创建了一个类库(.NET Framework 4.7.1),它使用属性在TSFITfTextInputProcessorEx中实现了文本服务(等) 。我使用它注册了它,它可以被系统成功识别为输入法(IME),并且可以在大多数应用程序中使用,除了 UWP 应用程序。ComVisibleRegistrationServices

在 Win32 应用程序中使用

在 Win32 应用程序(例如 32 位notepad.exe)中,当我激活基于 .NET 的 TextService(通过切换到语言栏中的 IME)时会发生以下情况:

在此处输入图像描述 (圈出YngPing.TSF.dll的是包含 COM 对象实现的 .NET 程序集。由 COM 对象创建引起的加载从 #56 开始。)

基本上,在切换到我的 IME 时,TSF 框架(不是应用程序代码,而是在同一进程中运行)将尝试通过调用来创建/请求我的 TextService 的 COM 对象CoCreateObject。因为这不是本机 COM 对象,mscoree.dll实际上是注册表中的“真实”COM DLL。mscoree.dll首先加载,然后加载mscoreei.dllclr.dll等等,最后加载实际的 .NET dll。

在 AppContainer 中使用(UWP 应用)

现在这些都在普通桌面应用程序中按预期工作,但在 UWP 应用程序中,相同的进程将在加载后停止mscoree.dllmscoreei.dllclr.dll,我的 .NET 程序集未加载)。调用堆栈如下所示:

在此处输入图像描述这里测试的 UWP 应用只是一个带有文本框的空白应用。所有这些 COM 加载都是由 TSF 发起的。

另一个观察:在调用mscoree.dll退出之后,内部的一个指针combase.dll被设置为E_NOTIMPL.

在此处输入图像描述

在同一个 UWP 应用程序中,可以毫无问题地加载和使用其他 3rd 方 IME 的 DLL(比如这个用 C++ 编写的https://github.com/rime/weasel )。我还没有测试官方示例,https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/IME ,但我很有信心它也会起作用。


我对正在发生的事情有一个粗略的了解,但我缺乏深入研究根本原因的专业知识:对于基于 .NET 的 COM 对象,会在请求 COM 对象时首先加载 CLR;但在这种情况下,对于 UWP,CLR 无法加载,随后 COM 对象无法启动。

我还使用了 Fusion Log(UWP 具有沉浸式模式),但没有看到任何相关消息。我想这是因为clr.dll在我的情况下甚至没有加载。

谁能提供一些关于如何解决这个问题的想法?谢谢!

更新:当我在这篇文章中说“IME”时,我的意思是“使用文本服务框架 API 的文本服务”,而不是传统的“输入法管理器 (IMM)”基于 API 的 IME。

4

1 回答 1

1

您不应该使用 .net 来编写 IME。我们只允许将单个版本的 .net 运行时加载到进程中。当您使用 .net 构建 IME 时,我们无法保证能够加载正确版本的运行时。因此,IME 可能会失败。您应该始终使用非托管 C++ 编写 IME 组件。

于 2018-06-26T02:05:58.023 回答