CLR не может создавать COM-объекты на основе.NET в UWP
Я создал библиотеку классов (.NET Framework 4.7.1), которая реализует текстовый сервис (ITfTextInputProcessorEx
и т. д.) в ФБО, используя ComVisible
приписывать. Я зарегистрировал это используя RegistrationServices
и он может быть успешно распознан системой как метод ввода (IME) и может использоваться в большинстве приложений, кроме приложений UWP.
Использование в приложении Win32
В приложении Win32 (32-разрядная notepad.exe
например), вот что происходит, когда я активирую свой Text Service на основе.NET (переключаясь на IME в языковой панели):
(Обведено
YngPing.TSF.dll
это сборка.NET, которая содержит реализацию COM-объекта. Загрузка, вызванная созданием COM-объекта, начинается с #56.)
По сути, после переключения на мой IME инфраструктура TSF (не код приложения, а выполняющийся в том же процессе) будет пытаться создать / запросить COM-объект моего Text Service, вызвав CoCreateObject
, Потому что это не нативный COM-объект, mscoree.dll
на самом деле "настоящая" COM DLL, которая находится в реестре. mscoree.dll
сначала загружается, потом загружается mscoreei.dll
, clr.dll
и т.д., прежде чем, наконец, загрузить фактическую.NET DLL.
Использование в AppContainer (приложение UWP)
Теперь все это работает, как и ожидалось, в обычных настольных приложениях, но в приложении UWP тот же процесс остановится после mscoree.dll
а также mscoreei.dll
загружены (т.е. clr.dll
и моя сборка.NET не загружается). Стек вызовов выглядит так:
(Тестируемое здесь приложение UWP - это просто пустое приложение с текстовым полем. Все эти загрузки COM инициируются ФБО.)
Еще одно наблюдение: после звонков mscoree.dll
выходит, один из указателей внутри combase.dll
установлен в E_NOTIMPL
,
В том же приложении UWP библиотеки DLL других IME сторонних производителей (например, https://github.com/rime/weasel написанные на C++) могут быть загружены и использованы без проблем. Мне еще предстоит протестировать официальный пример: https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/IME но я уверен, что он тоже будет работать.
У меня есть приблизительное представление о том, что происходит, но мне не хватает опыта, чтобы глубже погрузиться в основную причину: что происходит для COM-объектов на основе.NET, CLR загружается первым, когда запрашивается COM-объект; но в этом случае для UWP CLR как-то не удалось загрузить, и впоследствии COM-объект не может быть инициирован.
Я также использовал Fusion Log (с режимом погружения для UWP), но не видел связанных сообщений. Я думаю, это потому, что даже clr.dll
не загружается в моем случае.
Кто-нибудь может предложить какие-то идеи относительно того, как решить эту проблему? Спасибо!
Обновление: когда я говорю "IME" в этом посте, я имею в виду "текстовую службу, использующую API-интерфейс Text Service Framework", а не устаревшие IME на основе API "Input Method Manager (IMM)".
1 ответ
Вы не должны использовать.net для написания IME. Мы разрешаем загружать в процесс только одну версию среды.net. Когда вы создаете IME с помощью.net, мы не можем гарантировать, что сможем загрузить правильную версию среды выполнения. Из-за этого IME может потерпеть неудачу. Вы всегда должны писать свои компоненты IME, используя неуправляемый C++.