GetObject и VB6 ActiveX exe

Это может быть воспроизведено в Lua с помощью некоторой мета-магии: D

local function operator(func)
    return setmetatable({},
        {__sub = function(a, _)
            return setmetatable({a},
                {__sub = function(self, b)
                    return f(self[1], b)
                end}
            )
        end}
    )
end


local smartOr = operator(function(a, b)
    for i = 1, #b do
        if a == b[i] then
            return true
        end
    end
    return false
end)


local isPrimaryColor = someColor -smartOr- {"Red", "Blue", "Either"}

Примечание: Вы можете изменить имя -smartOr- на что-то вроде -isEither-, чтобы сделать его еще БОЛЬШЕ читаемым. ]

8
задан MarkJ 28 May 2009 в 10:16
поделиться

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 в ROT, поэтому GetObject не может получить ссылку на уже запущенный экземпляр.

Причина, по которой это не работает, заключается в том, как GetObject выполняет свою магию. Если первый параметр опущен, он пытается вернуть существующий экземпляр объекта, обращаясь к таблице запущенных объектов (ROT), таблице поиска для всей машины, содержащей запущенные COM-объекты. Проблема в том, что объекты должны быть явно зарегистрированы в таблице запущенных объектов процессом, который их создает, чтобы быть доступными для других процессов - среда выполнения VB6 не регистрирует классы ActiveX EXE в ROT, поэтому GetObject не может получить ссылку на уже запущенный экземпляр.

Причина, по которой это не работает, заключается в том, как GetObject выполняет свою магию. Если первый параметр опущен, он пытается вернуть существующий экземпляр объекта, обращаясь к таблице запущенных объектов (ROT), таблице поиска для всей машины, содержащей запущенные COM-объекты. Проблема в том, что объекты должны быть явно зарегистрированы в таблице запущенных объектов процессом, который их создает, чтобы быть доступными для других процессов - среда выполнения VB6 не регистрирует классы ActiveX EXE в ROT, поэтому GetObject не может получить ссылку на уже запущенный экземпляр.

таблица поиска для всей машины, которая содержит запущенные COM-объекты. Проблема в том, что объекты должны быть явно зарегистрированы в таблице запущенных объектов процессом, который их создает, чтобы быть доступными для других процессов - среда выполнения VB6 не регистрирует классы ActiveX EXE в ROT, поэтому GetObject не может получить ссылку на уже запущенный экземпляр.

таблица поиска для всей машины, которая содержит запущенные COM-объекты. Проблема в том, что объекты должны быть явно зарегистрированы в таблице запущенных объектов процессом, который их создает, чтобы быть доступными для других процессов - среда выполнения VB6 не регистрирует классы ActiveX EXE в ROT, поэтому GetObject не может получить ссылку на уже запущенный экземпляр.

10
ответ дан 5 December 2019 в 14:06
поделиться

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

Уловка состоит в том, чтобы помнить, что в ActiveX EXE его можно настроить так, чтобы был запущен только один экземпляр БИБЛИОТЕКИ. Верно, что вы не можете достичь и просто перехватить данный экземпляр класса через границу процесса. Однако ActiveX EXE можно настроить так, чтобы ГЛОБАЛЬНЫЕ переменные были доступны ЛЮБОМУ экземпляру классов.

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

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

Я настоятельно рекомендую вам создать ActiveX DLL (не 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

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

Затем вы идете

'Class ThisGUIApp
Public MainForm as IMainForm

Private Sub Class_Initialize
  Set MainForm = frmMyMainForm
End Sub

'Form frmMyMainForm
Implements IMainForm

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

Затем вы идете

'Class ThisGUIApp
Public MainForm as IMainForm

Private Sub Class_Initialize
  Set MainForm = frmMyMainForm
End Sub

'Form frmMyMainForm
Implements IMainForm

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

2
ответ дан 5 December 2019 в 14:06
поделиться