Тайм-аут COM-сервера - PullRequest
       84

Тайм-аут COM-сервера

2 голосов
/ 21 апреля 2020

У меня есть приложение Win32 / MF C, которое зависит от двух отдельных серверов STA COM DLL, которые я создавал много лет go с использованием C ++ / ATL. Это большие DLL-серверы с несколькими интерфейсами, которые также успешно используются в других контекстах и ​​клиентских программах. Несколько лет go мне приходилось создавать 64-битные версии этих 32-битных серверов, и мое 32-битное приложение MF C должно было иметь возможность использовать 32-битную или 64-битную версию DLL COM сервер (выбирается с помощью флажка).

Поскольку 32-разрядный процесс не может загрузить 64-разрядную DLL-библиотеку COM-сервера в процессе, я обошел эту проблему, заставив приложение MF C создать 64-разрядные серверы в суррогате системы ( DLLHOST.EXE), заменив

CoCreateInstance(..., CLSCTX_INPROC_SERVER, ...)

на

CoCreateInstance(..., CLSCTX_LOCAL_SERVER | CLSCTX_ACTIVATE_64_BIT_SERVER, ...)

Потребовались некоторые обновления, такие как добавление интерфейса для копирования переменных среды в процесс сервера и установка рабочего каталога сервера / суррогата (суррогат начинается в SYSTEM32), но все остальные интерфейсы были удаленными. Кажется, что все это работает идеально, и теперь я могу использовать 32-разрядные и 64-разрядные серверы взаимозаменяемо из 32-разрядного приложения, щелкая переключатель.

Однако есть одна проблема, которой у меня нет был в состоянии решить: заставить суррогат быстро завершиться, когда клиент выпустит последний интерфейс . Суррогат зависает в течение 3-5 секунд после того, как клиент MF C освободил все удаленные интерфейсы - вероятно, оптимизация, надеясь, что клиент вернется. Если приложение MF C повторно запускает сервер с CoCreateInstance () в течение этих 3-5 секунд, оно повторно подключается к тому же «грязному» суррогату. Код сервера не может использоваться повторно последовательно (он упаковывает многие тысячи строк устаревшего кода ANSI "C" с большим количеством переменных * stati c), поэтому повторное подключение к одному и тому же экземпляру просто невозможно.

Я несколько лет работал над этим go, заставляя интерфейс запуска возвращать код ошибки COM, указывающий, что сервер ожидает перезапуска (лучше, чем cra sh). Однако серверы запускаются, когда конечный пользователь нажимает кнопку панели инструментов в приложении MF C, поэтому это означает, что пользователь получает сообщение типа «подождите несколько секунд и повторите попытку». Это работает, но плохо то, что каждая попытка запуска fre sh сбрасывает счетчик 3-5 секунд, который удерживает суррогат от выхода. И нетерпеливые пользователи жалуются. Я добавлю, что все это работает идеально в процессе, с CoFreeUnusedLibraries(), работающим как ожидалось.

Я уже пробовал несколько вещей - все, кроме кодирования ExitProcess() на сервере, что кажется неуместным , Кажется, нет никакого способа сказать суррогату, что приложение завершено и не должно ждать новых подключений. Документация MS утверждает, что без атрибута RunAs в AppID может помочь (у меня было установлено "Интерактивный пользователь" ), но это не так. Он также упоминает REGCLS_SINGLUSE, но затем говорит "Не устанавливайте REGCLS_SINGLUSE или REGCLS_MULTIPLEUSE при регистрации суррогата для серверов DLL" и "REGCLS_SINGLUSE и REGCLS_MULTIPLEUSE не должны использоваться для серверов DLL, загруженных в суррогаты. « и я не могу контролировать фабрику классов суррогата, насколько мне известно.

Похоже, что COM + может обеспечить некоторый контроль над переработкой, так как, кажется, имеет RecycleActivationLimit вариант, который я мог бы установить на 0, но я понятия не имею, что потребуется, чтобы преобразовать это в сервер COM +.

Другая возможность - написать собственный суррогат.

Если нет простого ответа, я мог бы просто прибегнуть к потере кнопки до тех пор, пока сервер не исчезнет, ​​но, поскольку я не могу исследовать сервер, не продлив его время жизни, я думаю, что я мог бы добавить общий мьютекс и подожди пока вани sh. Тьфу.

RecycleActivationLimit так или иначе доступен для обычных приложений COM? Любые другие предложения приветствуются.

...