我创建了一个类库(.NET Framework 4.7.1),它实现了文本服务(ITfTextInputProcessorEx
等)中TSF https://msdn.microsoft.com/en-us/library/windows/desktop/ms629032(v=vs.85).aspx, using ComVisible
属性。我注册它使用RegistrationServices
它可以被系统成功识别为输入法 (IME),并且可以在除 UWP 应用程序之外的大多数应用程序中使用。
在 Win32 应用程序中使用
在 Win32 应用程序中(32 位notepad.exe
例如),当我激活基于 .NET 的 TextService(通过切换到语言栏中的 IME)时,会发生以下情况:
(The circled YngPing.TSF.dll
is the .NET assembly that contains the implementation of the COM object. The loading caused by COM object creation starts at #56.)
基本上,在切换到我的 IME 后,TSF 框架(不是应用程序代码,而是在同一进程中运行)将尝试通过调用来创建/请求我的 TextService 的 COM 对象CoCreateObject
。因为这不是本机 COM 对象,mscoree.dll
实际上是注册表中的“真正的”COM DLL。mscoree.dll
首先加载,然后加载mscoreei.dll
, clr.dll
等等,然后才最终加载实际的 .NET dll。
在AppContainer(UWP应用程序)中使用
现在,这些在普通桌面应用程序中都按预期工作,但在 UWP 应用程序中,相同的过程将在mscoree.dll
and mscoreei.dll
已加载(即clr.dll
并且我的 .NET 程序集未加载)。调用堆栈如下所示:
(The UWP app tested here is just an blank app with a textbox. All these COM loading are all initiated by the TSF.)
另一个观察结果:在致电之后mscoree.dll
quits,里面的指针之一combase.dll
被设定为E_NOTIMPL
.
在同一个 UWP 应用程序中,其他第 3 方 IME 的 DLL(例如这个)https://github.com/rime/weasel https://github.com/rime/weasel用 C++ 编写)可以毫无问题地加载和使用。我还没有测试官方的例子,https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/IME 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。