Несколько квартир VB6 в приложении C #

У нас есть очень старое устаревшее приложение vb6, у которого есть один глобальный объект, который служит ядром приложения, хранит различные настройки приложения, вызывает операции с базой данных и так далее. Несколько модулей с разными прогидами используют этот глобальный объект и не имеют с ним проблем из-за однопоточного апартамента.

Не так давно было создано новое приложение WPF, обеспечивающее переход с vb6, однако оно все еще ограничено наследием vb6 из-за некоторых архитектурных ошибок. Он может подключаться только к одной базе данных для каждого экземпляра приложения. Он содержит статический экземпляр глобального объекта vb6 в классе оболочки, который служит мостом для достижения унаследованных функций.

Сейчас мы разрабатываем новое приложение, которое не должно быть ограничено старым устаревшим кодом, в частности, новое приложение должно иметь возможность подключаться к нескольким базам данных одновременно, но есть загвоздка: код vb6 ограничен одной базой данных, поэтому должен быть несколько экземпляров глобальных объектов vb6, по одному на каждую базу данных.

Возникает вопрос: возможно ли это, и если да, то как можно использовать несколько отдельных экземпляров глобальных объектов vb6 в одном приложении C #?

Я предполагаю, что каждый экземпляр такого объекта должен жить в своем собственном STA-потоке, но я не знаю, как создавать такие потоки, которые поддерживаются в течение всего времени выполнения приложения и имеют связанные оболочки, содержащие экземпляры глобальных объектов vb6 и поддерживающие вызов некоторых функций из потока GUI (а как организовать такое межпотоковое взаимодействие, thread.invoke (...)). Я думал об использовании модели диспетчеризации wpf (класс оболочки - DispatcherObject, у каждого экземпляра есть собственный Dispatcher с собственным STA-потоком), но я не вижу, как это реализовать. Также я думаю, что это можно реализовать, загрузив каждый экземпляр класса оболочки (статический) в разные домены приложений, но я не знаю, решает ли он проблему STA для COM.


person Aloraman    schedule 29.10.2013    source источник
comment
Интересный вопрос. Вы уверены, что просто перекодировать глобальный объект vb6 в C # не будет меньше проблем (и будет надежнее, проще в обслуживании и т. Д.)?   -  person Robert Harvey    schedule 29.10.2013
comment
Мы не можем просто перекодировать глобальный код vb6, потому что нам придется перекодировать каждый модуль vb6, который его использует - а это много работы (и никто даже не хочет его трогать, было бы гораздо проще переписать эти модули на C # с нуля. Но это тоже займет много времени, поэтому мы пытаемся добиться обратной совместимости со старыми модулями в новом приложении)   -  person Aloraman    schedule 29.10.2013
comment
Это встроенная возможность VB6. Если вы настроили его правильно, то при повторном создании объекта Application должен запускаться другой экземпляр внепроцессного сервера. Полностью изолированный от первого, он может разговаривать со своей собственной базой данных.   -  person Hans Passant    schedule 29.10.2013
comment
Вы можете перекодировать глобальный объект VB6, но использовать новую версию только в новом коде .NET. Существующий код продолжит использовать старый объект VB6.   -  person John Saunders    schedule 29.10.2013
comment
Также обратите внимание, что глобальный объект VB6 может некорректно работать в нескольких потоках. Сколько десятилетий существовал только один поток, и теперь вы хотите изменить предположение о том, что существует только один поток. Не похоже на хорошую идею.   -  person John Saunders    schedule 30.10.2013
comment
@Hans Passant, да, он работает для внепроцессного сервера (но с ограничениями, я полагаю, мой коллега сказал, что ему удалось повлиять на работу одного процесса, запущенного как автономный exe, на который влияет тот же exe, запущенный под визуальным отладчик studio 6). Но этот глобальный объект vb6 на самом деле является внутрипроцессным сервером, хранящимся в dll, на который ссылается старое приложение exe (которое, таким образом, хранится в STA этого потока exe) и проект класса оболочки в новом приложении   -  person Aloraman    schedule 30.10.2013
comment
Хм, приложение - довольно плохой выбор для имени. Технически возможно размещение их в отдельных процессах .NET. Однако в спешке он превращается в Летающий цирк Монти Пайтона.   -  person Hans Passant    schedule 30.10.2013
comment
@John Saunders, и это причина изолировать разные глобальные объекты в собственных потоках. Если два глобальных объекта хранятся в одном потоке, то каждый загруженный модуль vb (dll, зарегистрированный в системе regsvr32 и загруженный Microsoft.VisualBasic.Interaction.CreateObject (progid)) видит только последний глобальный объект   -  person Aloraman    schedule 30.10.2013
comment
Проблема не только в потоках. Потоки не независимы друг от друга. Код, выполняющийся в двух разных потоках, может по-прежнему использовать общую память, если код был написан так, чтобы предполагать, что существует только один поток.   -  person John Saunders    schedule 30.10.2013
comment
@HansPassant Настоящее имя намного ужаснее: Kernel \ tickApplic.cAppGlobal ... этот код не старый - он древний :(. В любом случае, если это технически возможно, не могли бы вы дать мне некоторые подробности о возможной реализации?   -  person Aloraman    schedule 30.10.2013
comment
Возможно, вам удастся запустить один экземпляр глобального объекта для каждого домена приложения. В целях безопасности вы должны запускать каждый из них в отдельном процессе, поскольку это предположение, на основе которого они были созданы. Я гарантирую вам, что ужасные вещи могут случиться, когда вы нарушите предположения древнего кода - особенно когда вы познакомите их с вещами, которых просто не существовало, когда они были написаны.   -  person John Saunders    schedule 30.10.2013
comment
@JohnSaunders, я вижу. Пожалуйста, опубликуйте это как ответ, чтобы я мог принять это   -  person Aloraman    schedule 30.10.2013


Ответы (2)


Вы можете обойтись без запуска одного экземпляра глобального объекта на AppDomain.

В целях безопасности вы должны запускать их каждый в своем собственном процессе, поскольку это предположение, на основе которого они были созданы. Я гарантирую вам, что ужасные вещи могут случиться, когда вы нарушите предположения древнего кода - особенно когда вы познакомите их с вещами, которых просто не существовало, когда они были написаны.

person John Saunders    schedule 30.10.2013
comment
VB6 использует TLS для глобального состояния. Единственный способ поделиться состоянием между потоками - это вызовы маршалированных функций COM. Таким образом, на самом деле очень безопасно использовать одноэлементный объект для каждого потока - в этом случае не нарушаются никакие предположения. Единственная проблема - разрывы потоков STA из-за утечки среды выполнения, и это не было исправлено. А потом MS отказался от всего языка. - person wqw; 31.10.2013
comment
Так не пойдет. VB6, COM, не имеет понятия о доменах приложений .NET. Если состояние VB6 является глобальным для загруженного процесса, оно остается неизменным независимо от того, в скольких доменах приложений находится ваш код .NET. - person Jerome Haltom; 27.07.2020

Это возможно, используя так называемый неуправляемый код. Проверьте это: http://www.codeproject.com/Articles/154144/Using-Unmanaged-VB6-Code-in-NET

person Community    schedule 29.10.2013