.Net Core и COM
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.11.17 11:14
Оценка:
Замутил тестовый проект под .Net Core (NETCOREAPP2_0), создающий COM-объект.

Получаю ошибку вызова CoCreateInstance — 0x800401F0 (CO_E_NOTINITIALIZED — CoInitialize has not been called).

Указание атрибута [MTAThread] не помогает.

[MTAThread]
static void Main(string[] args)

Подскажите — как заставить Core инициализировать COM?

Ну, кроме кроме явного вызова CoInitialize, конечно.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: .Net Core и COM
От: Arsen.Shnurkov  
Дата: 06.11.17 13:26
Оценка: 12 (2)
я думаю, надо написать
Thread.CurrentThread.TrySetApartmentState(ApartmentState.MTA);
Отредактировано 06.11.2017 13:42 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 06.11.2017 13:39 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 06.11.2017 13:31 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 06.11.2017 13:29 Arsen.Shnurkov . Предыдущая версия .
Re[2]: .Net Core и COM
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.11.17 14:35
Оценка: 48 (1)
Здравствуйте, Arsen.Shnurkov, Вы писали:

AS>я думаю, надо написать

AS>Thread.CurrentThread.TrySetApartmentState(ApartmentState.MTA);

Помогло, спасибо.

Я верну назад ссылку, которую ты стер

https://github.com/dotnet/coreclr/issues/13688#issuecomment-326759385

Насколько я понимаю, бардак до сих пор присутствует.

  Тестовый код
  static void Main(string[] args)
  {
   try
   {
    var curAState=System.Threading.Thread.CurrentThread.GetApartmentState();

    Console.WriteLine("GetApartmentState: {0}",curAState);

    bool r=System.Threading.Thread.CurrentThread.TrySetApartmentState(System.Threading.ApartmentState.MTA);

    Console.WriteLine("TrySetApartmentState(MTA): {0}",r);

    Exec();
   }
   catch(Exception e)
   {
    Console.WriteLine("ERROR: {0} - {1}",e.Source,e.Message);
   }
  }//Main

Вывод:
GetApartmentState: MTA
TrySetApartmentState(MTA): True

Получается, что COM не инициализирован, но GetApartmentState возвращает обратное (MTA).

Еще отмечу, что нужно принудительно освобождать ссылки на COM-объекты (диспозить/закрывать .NET обертки) перед выходом из Main.

Иначе, при завершении главного потока, происходит выгрузка DLL с активными COM-объектами.
  И вылазят проблемы типа такой:

GetApartmentState: MTA
TrySetApartmentState(MTA): True
Assertion failed:
module_lock_count: 2
false, file ..\source\ibp_com.cpp, line 112


На нормальном .NET FW с этим можно было не париться.

UPD. Добавил в конец Main принудительную(?) сборку мусора. Вроде тоже помогает освободить все ссылки на COM-объекты:
 GC.Collect();
 GC.WaitForPendingFinalizers();
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 06.11.2017 14:48 DDDX . Предыдущая версия .
Re[3]: .Net Core и COM
От: Sinix  
Дата: 06.11.17 15:42
Оценка: 104 (5) +1 :)
Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>UPD. Добавил в конец Main принудительную(?) сборку мусора. Вроде тоже помогает освободить все ссылки на COM-объекты:


Опередил Это ещё одно гениальное решение команды .Net core: вызов финалайзеров более не гарантирован даже при мягком завершении процесса. Угу, CLI, ecma-335 и прочая куча умных слов — не, не слышал.

Логики в этом нет, поэтому или ждать, пока команда net core сама перенаступает на грабли, которые были решены ещё в первом фреймворке, или оставаться на full .NET.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.