问题
I have created a Class Library (.NET Framework 4.7.1) that implements a Text Service (ITfTextInputProcessorEx
etc.) in TSF, using ComVisible
attribute. I registered it using RegistrationServices
and it can be successfully recognised by the system as an Input Method (IME) and can be used in most applications, except UWP apps.
Using in Win32 app
In a Win32 app (the 32-bit notepad.exe
for example), here is what happens when I activate my .NET-based TextService (by switching to the IME in the language bar):
(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.)
Basically, upon switching to my IME, the TSF framework (not the application code, but running in the same process) will try to create/request a COM object of my TextService by calling CoCreateObject
. Because this not a native COM object, mscoree.dll
is actually the "real" COM DLL that is in the registry. mscoree.dll
first gets loaded, then it loads mscoreei.dll
, clr.dll
etc., before finally loading the actual .NET dll.
Using in AppContainer (UWP app)
Now these all works as expected in normal Desktop apps, but in an UWP app, the same process will stop after mscoree.dll
and mscoreei.dll
are loaded (i.e. clr.dll
and my .NET assembly are not loaded). The call stack looks like this:
(The UWP app tested here is just an blank app with a textbox. All these COM loading are all initiated by the TSF.)
Another observation: after the calls to mscoree.dll
quits, one of the pointers inside combase.dll
is set to E_NOTIMPL
.
In the same UWP app, DLLs of other 3rd party IMEs (like this one https://github.com/rime/weasel written in C++) can be loaded and used without problem. I am yet to test the official example, https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/IME but I am pretty confident it will work too.
I have a rough idea of what's going on, but I lack the expertise to dive deeper into the root cause: what happens is for .NET-based COM objects, the CLR is loaded first when the COM object is requested; but in this case for UWP, the CLR somehow failed to load and subsequently the COM object cannot be initiated.
I also used Fusion Log (with immersive mode for UWP) but did not see any related messages. I guess it is because even clr.dll
is not loaded in my case.
Can anyone offer some ideas as to how to solve this problem? Thanks!
Update: When I say "IME" in this post, I mean "a Text Service using the Text Service Framework API", not the legacy "Input Method Manager (IMM)" API-based IMEs.
回答1:
You shouldn’t be using .net to write an IME. We only allow a single version of the .net runtime to be loaded into a process. When you build an IME with .net we cannot guarantee that we will be able to load the correct version of the runtime. Because of this the IME may fail. You should always write your IME components using unmanaged C++.
来源:https://stackoverflow.com/questions/50660726/clr-cannot-create-net-based-com-objects-in-uwp