.Чистая внепроцессного com-объектов совместного использования статических экземпляров в вызовы API


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

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

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

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

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

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

3 3

3 ответа:

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

Http://msdn.microsoft.com/en-us/library/ms693407 (v=против 85).aspx , и

Http://msdn.microsoft.com/en-us/library/ms679697 (v=против 85).aspx

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

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

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

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

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

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

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