GetObject и VB6 ActiveX exe
В в VB6 справка по GetObject говорит: "Вы не можете использовать GetObject для получения ссылки на класс, созданный с помощью Visual Basic" (последнее предложение!). Мой графический интерфейс VB6 предоставляет объекты в виде ActiveX exe для других компонентов. Я хочу, чтобы другие компоненты подключались к GUI, который уже запущен, а не запускали новый экземпляр exe. Я обнаружил, что использование GetObject работает, если вы используете этот синтаксис:
Set myobj = GetObject("", "ProjectName.ClassName")
меня беспокоит, что помощь говорит это не должно работать, хотя я провел довольно много тестов и до сих пор не нашел никаких проблем. Любые эксперты COM там, кто может сказать мне, собираюсь ли я столкнуться с проблемами в будущем? И буду ли я в порядке с CreateObject в любом случае?
параметры ActiveX exe: пул потоков только с одним потоком. Класс имеет многоцелевой экземпляр. Возможно, этих параметров достаточно, чтобы предотвратить запуск CreateObject нового экземпляра exe в любом случае. Это верно?
2 ответов
документация запутанная, но правильная. Страница MSDN ссылка помогает объяснить, почему ваш GetObject
вызов не выдает ошибку:
если путь [первый аргумент] является строкой нулевой длины ( "" ),GetObject возвращает новый объект экземпляр указанного типа. Если аргумент pathname опущен, GetObject возвращает текущий активный объект указанный тип. Если нет объект указанного типа существует, возникает ошибка.
это тонко, но подразумевается, что
GetObject "", "ProjectName.ClassName
фактически эквивалентно
CreateObject "ProjectName.ClassName"
то есть передача пустой строки первому параметру GetObject
заставляет его работать так же, как CreateObject
, что означает, что он создаст новый экземпляр класса, а не возвращать ссылку на уже запущенный пример.
возвращаясь к выдержке MSDN, он упоминает, что опуская первый аргумент GetObject
всего вызовет GetObject
, чтобы вернуть ссылку на уже запущенный экземпляр, если таковой существует. Такой звонок будет выглядеть так:
GetObject , "ProjectName.ClassName" 'Note nothing at all is passed for the first argument'
однако, если вы попытаетесь сделать это, вы сразу получите ошибку времени выполнения. Это прецедент, на который ссылается документация, когда она говорит, что GetObject
не работает с классами, созданными с VB6.
причина, по которой это не работает, заключается в том, как GetObject
выполняет свою магию. Если первый параметр опущен, он пытается вернуть существующий экземпляр объекта, обратившись к таблице запущенных объектов (ROT), машинной таблице поиска, содержащей запущенные COM-объекты. Проблема в том, что объекты должны быть явно зарегистрированы в таблице запущенных объектов процессом, который их создает , чтобы быть доступными для других процессов-среда выполнения VB6 не регистрирует ActiveX EXE занятия в гнили, так что GetObject
не имеет возможности получить ссылку на уже запущенный экземпляр.
Я хочу, чтобы другие компоненты для подключения к GUI, который уже запущен, вместо того, чтобы начать новый экземпляр EXE-файл.
хитрость заключается в том, чтобы помнить, что в ActiveX EXE он может быть настроен так, что есть только один экземпляр библиотеки работает. Правильно, что вы не можете достичь и просто вырвать данный экземпляр класса через границу процесса. Однако ActiveX EXE можно настроить так, чтобы глобальные переменные были доступны любому экземпляру занятия.
как именно это сделать, становится немного сложным. Вы можете использовать ActiveX EXE как обычный EXE основное отличие заключается в том, что вы должны использовать Sub Main. Вы также можете проверить, работает ли он автономно или нет. Теперь я предполагаю, что это дело с применением MarkJ по.
Если это так, то вам нужно создать класс приложения и настроить его так, чтобы при его создании (с помощью Class_Initialize) он заполнялся текущим запуском экземпляры форм и коллекций.
я настоятельно рекомендуем вам создать ActiveX DLL (не EXE), которая не имеет ничего, кроме классов для реализации в качестве интерфейсов. Вместо того, чтобы идти
'Class ThisGUIApp
Public MainForm as Form
создать интерфейс, который имеет все свойства и методы, необходимые для доступа к элементам форму mainform. Тогда вы идете
'Class ThisGUIApp
Public MainForm as IMainForm
Private Sub Class_Initialize
Set MainForm = frmMyMainForm
End Sub
'Form frmMyMainForm
Implements IMainForm
вы делаете это, потому что, хотя вы можете отправить форму через процесс приложения, все становится шатким, когда вы пытаетесь получить доступ к его членам и контроль. Если вы назначены через интерфейс, то соединение намного более прочное. Кроме того, он лучше документирует тип вещей, которые вы пытаетесь сделать.