GetObject и VB6 ActiveX exe - PullRequest
       19

GetObject и VB6 ActiveX exe

8 голосов
/ 27 мая 2009

Справка VB6 по GetObject гласит: «Вы не можете использовать GetObject для получения ссылки на класс, созданный с помощью Visual Basic» (самое последнее предложение!). Мой графический интерфейс VB6 предоставляет объекты в виде файла ActiveX для других компонентов, которыми можно манипулировать. Я хочу, чтобы другие компоненты подключались к уже запущенному графическому интерфейсу, а не запускать новый экземпляр exe. Я обнаружил, что использование GetObject работает, если вы используете этот синтаксис:

Set myobj = GetObject("", "ProjectName.ClassName")

Меня беспокоит, что справка говорит, что это не должно работать, хотя я провёл немало тестов и до сих пор не обнаружил никаких проблем. Любые эксперты COM, которые могут сказать мне, столкнусь ли я с проблемами в будущем? И все ли я буду в порядке с CreateObject?

Настройки ActiveX exe: пул потоков только с одним потоком. Класс имеет многократное использование. Возможно, этих настроек достаточно, чтобы CreateObject не запускал новый экземпляр exe. Это правильно?

Ответы [ 2 ]

10 голосов
/ 27 мая 2009

Документация запутанная, но правильная. Страница MSDN, на которую вы ссылаетесь, помогает объяснить, почему ваш GetObject вызов не выдает ошибку:

Если путь [ первый аргумент ] является строкой нулевой длины (""), GetObject возвращает новый объект экземпляр указанного типа. Если аргумент пути не указан, 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 в ROT, поэтому GetObject не имеет способ получить ссылку на уже работающий экземпляр.

2 голосов
/ 23 сентября 2009

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

Хитрость заключается в том, чтобы помнить, что в ActiveX EXE его можно настроить так, чтобы работал только один экземпляр БИБЛИОТЕКИ. Это правильно, что вы не можете достать и просто отобрать данный экземпляр класса через границу процесса. Однако ActiveX EXE может быть настроен так, чтобы переменные GLOBAL были доступны ЛЮБОМУ экземпляру классов.

Как именно это сделать, становится немного сложнее. Вы можете использовать ActiveX EXE как обычный EXE, главное отличие в том, что вы ДОЛЖНЫ использовать Sub Main. Вы также можете проверить, работает ли он автономно или нет. Теперь я предполагаю, что это так с приложением MarkJ.

В этом случае вам нужно создать класс приложения и настроить его так, чтобы при его создании (с помощью Class_Initialize) он заполнялся текущими запущенными экземплярами форм и коллекций.

Я настоятельно рекомендую вам создать DLL ActiveX (не EXE), в которой есть только классы для реализации в качестве интерфейсов. Вместо того, чтобы идти

'Class ThisGUIApp
Public MainForm as Form

Вы создаете интерфейс, который имеет все свойства и методы, необходимые для доступа к элементам основной формы. Тогда вы идете

'Class ThisGUIApp
Public MainForm as IMainForm

Private Sub Class_Initialize
  Set MainForm = frmMyMainForm
End Sub

'Form frmMyMainForm
Implements IMainForm

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

...