COM-объекты вне процесса .NET, совместно использующие статические экземпляры в вызовах API - PullRequest
3 голосов
/ 26 мая 2011

Трудно объяснить нашу ситуацию.

У нас есть 3-х уровневое приложение. Движок - это DLL, написанная на C ++, затем у нас есть VX6 ActiveX EXE, который обращается к движку через вызовы API, а на верхнем уровне у нас есть надстройка Excel (в C # с использованием инфраструктуры VSTO), вызывающая средний уровень с помощью DLL взаимодействия. , В это время каждое «подключение» от Addin к движку создает новый EXE (VB6 использует вызовы API для доступа к движку), и все работает нормально. Теперь мы перемещаем средний уровень в .NET, он работает «предположительно» нормально (он проходит все наши юнит-тесты), но мы обнаружили ошибку, когда открываем 2 «соединения» одновременно (ups, ни один юнит-тест не проверяет эту ситуацию) потому что это новое поведение). В DLL есть статические объекты, которые используются всеми экземплярами одного и того же процесса, и мы взаимодействуем между «соединениями». В нашей старой версии каждое «соединение» создает новый EXE-файл без разделения памяти между процессами, теперь это один и тот же процесс, и они совместно используют память и статические объекты.

Следуя подсказкам , этот вопрос . Мы пытались собрать COM EXE в C #, чтобы сделать объекты вне процесса на среднем уровне, но у нас тот же результат. Они разделяют статические объекты, в конце каждое соединение не создает независимый процесс.

Понятно, но в настоящее время это недопустимо, перемещая вызовы API в ATL или изменяя статические объекты на инстанцируемые ссылки с дескриптором и изменяя все вызовы API, чтобы получить / установить эти обработчики. Я рассмотрел все примеры в MS All-in-one , но не нашел решения. Также невозможно сохранить только одно соединение за раз, каждая книга может иметь одно соединение, и в будущем мы хотим исследовать веб-приложение с несколькими соединениями одновременно.

Есть предложения?

Заранее спасибо,

Ответы [ 3 ]

3 голосов
/ 06 июня 2011

Независимо от того, запускает ли COM новый EXE-файл для каждого COM-объекта или использует один EXE-файл для создания экземпляра всего объекта, он контролируется параметрами флагов, передаваемых в CoRegisterClassObject. См

http://msdn.microsoft.com/en-us/library/ms693407(v=vs.85).aspx, и

http://msdn.microsoft.com/en-us/library/ms679697(v=vs.85).aspx

Вам необходимо передать флаги REGCLS_SINGLEUSE или REGCLS_MULTI_SEPARATE.

Теперь уловка состоит в том, чтобы передать этот флаг, так как вы не можете вызывать этот метод напрямую - детали зависят от того, как вы реализовали COM EXE.

2 голосов
/ 26 мая 2011

это не ясно из вопроса, но похоже, что «средний уровень», который вы создали, был создан как VB6 EXE, и вы пытаетесь заменить его на .net DLL. Если это так, то вы обязательно получите описанное вами поведение.

В проекте com с VB6 EXE создание нового объекта запускает новый процесс. С .net dll (или на самом деле Vb6 dll) вы + не получите + новый процесс.

Вам нужно либо создать EXE-файл .net, который предоставляет COM-объекты точно так же, как это делает ваш VB6 exe, либо (похоже, вы уже исследовали это), вам нужно реорганизовать ваши EXE-объекты для правильной обработки нескольких экземпляров в течение одного процесса.

Честно говоря, вероятно, было бы лучше сделать это последним, поскольку полагаться на одиночные игры, как это, как правило, неприятный запах кода. Но в крайнем случае, вы должны быть в состоянии повторить поведение VB6 exe с проектом .net. Вы просто не можете сделать это в DLL.

1 голос
/ 08 июня 2011

Был ли ваш средний слой создан в .Net? Если это так, вы можете столкнуться с проблемой того, что ваш COM-класс создан как собственный объект .net вместо COM-объекта. Решение обычно включает использование Первичных сборок взаимодействия . Посмотрите на этот вопрос , чтобы увидеть, соответствует ли он вашей проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...