Registration-free COM
От: xhalt Украина  
Дата: 13.01.06 16:52
Оценка:
Привет всем!

Задача:
Обеспечить возможность использования СOM-компонентов (DLL-серверов) инсталлированных локально в каталоге приложения без (обязательной) предварительной регистрации в реестре.
С такими COM-компонентами должны работать клиенты, написанные с помощью
ATL/MFC.По возможности, должна обеспечиваться поддержка любых других COM-клиентов и
COM-серверов выполняющиеся в адресном пространстве приложения без необходимости внесения изменения в их код, например таких как .NET COM Interop (RCW/CCW в CLR), VB6-контролы, использующие другие ActiveX'ы и т.п.
Операционные системы: Win9x,NT,2000,XP,2003
Мотивация:
Видимый вариант решения:
Перехват системного CoCreateInstance, по схеме "Detours".
Написание собственного CustomCoCreateInstance, который читает некоторые метаданные хранимые в каталоге .exe (аналогичные по структуре записям реестра для COM-компонентов), если находит информацию — загружает вручную DLL и выполняет цепочку действий для инстанциации COM-объекта и получения интерфейса. В случае отсутствия информации — обращается к системной CoCreateInstance.

Какие будут идеи, замечания, альтернативные предложения, дополнительные мотивации, другие пути решения?

--
Regards, xhalt


Предлагаю работу в Киеве
Автор:
Дата: 04.05.06
Re: Registration-free COM
От: AndrewJD США  
Дата: 13.01.06 17:12
Оценка:
Здравствуйте, xhalt, Вы писали:

Пара вопросов:

X>Мотивация:

X>
  • упрощение развертывания (включая возможность запуска приложений непосредственно с CD)
    +1

    X>
  • решение известных проблем версионности COM
    Можно подробней какие именно проблемы версионности СОМ решит этот похдод?

    X>
  • обеспечение возможности одновременной работы с различными версиями ActiveX но с одинаковыми GUID-ами коклассов или progid.
    Зачем это нужно? Ведь progid и придумывали, чтобы различать версии
  • "For every complex problem, there is a solution that is simple, neat,
    and wrong."
    Re[2]: Registration-free COM
    От: xhalt Украина  
    Дата: 13.01.06 17:38
    Оценка:
    X>>решение известных проблем версионности COM
    X>>обеспечение возможности одновременной работы с различными версиями ActiveX но с одинаковыми GUID-ами коклассов или progid.
    AJD>Можно подробней какие именно проблемы версионности СОМ решит этот похдод?
    AJD>Зачем это нужно? Ведь progid и придумывали, чтобы различать версии
    Собственно старая дилема:
    изменять ли ProgID (и/или co-class guid) при любом изменении кода компоненты (не затрагивающей изменение интерфейса)
    почему дилема?
    Ещё проблемы инсталляции/деинсталляции в случае если компонент общий (решаемые конечно проблемы, но могло бы их и не быть)

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


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re: Registration-free COM
    От: softilium Россия http://www.pristroy.com
    Дата: 13.01.06 19:27
    Оценка:
    Здравствуйте, xhalt, Вы писали:

    X>Обеспечить возможность использования СOM-компонентов (DLL-серверов) инсталлированных локально в каталоге приложения без (обязательной) предварительной регистрации в реестре.


    Собственно, меняется только использование таких объектов, а не их написание. Довольно небольшая дописка требуется для загрузки нужной библиотеки вручную, получение ее фабрики классов и затем от этой фабрики нужных коклассов, которые, как Вы справедливо заметили, в этом случае могут быть сугубо локальными (мы то точно знаем, какой файл библиотеки загрузили и реестр нас не интересует). Насколько я понимаю, это оставляет проблему регистриуемых глобально интерфейсов (type library), коклассы могут быть локальны, но наверное и этот вопрос можно решить, я просто не заморачивался.

    Делал описанную вещь неоднократно, но Вас врядли заинтересует пример кода на Delphi.
    Re[2]: Registration-free COM
    От: xhalt Украина  
    Дата: 13.01.06 20:39
    Оценка:
    Здравствуйте, softilium, Вы писали:
    S>Собственно, меняется только использование таких объектов, а не их написание.
    Совершенно верно сами COM-сервера менять не предполагается да и лишнее это.
    Однако, хотелось бы и не менять использование (детальнее поясняю ниже)
    S>Довольно небольшая описка требуется для загрузки нужной библиотеки вручную....
    Ручная загрузка библиотеки, инстанциация объекта через фабрику и получение указателя на нужные интерфейсы — задача достаточно тривиальная. Если мы можем модифицировать код, который использует COM (заменить вызовы CoCreateInstance на CoCreateInstanceFromDll) — то вроде бы всё прозрачно.

    Но есть случаи и такого типа:
    [EXE] -> [Some COM Client] -> [SomeActiveX.dll]
    [EXE] — наше приложение,
    [Some COM Client] некий COM-клиент, который использует компоненту [SomeActiveX.dll].
    Оба развёртываются в каталог приложения [EXE]. Причём [Some COM Client] —
    модифицировать нельзя, так как это компонента стороннего производителя (нет исходных текстов),
    или даже некая часть системы (RCW в .NET).
    Таким образом задача состоит в том, чтобы заставить [Some COM Client] находить или использовать локальную [SomeActiveX.dll] не зарегистрированную в реестре.

    S>Делал описанную вещь неоднократно,

    S>но Вас врядли заинтересует пример кода на Delphi.
    Меня — нет, но, возможно, готовый пример будет кому-нибудь полезен.


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re: Registration-free COM
    От: Юнусов Булат Россия  
    Дата: 14.01.06 02:52
    Оценка:
    Здравствуйте, xhalt, Вы писали:

    http://msdn2.microsoft.com/en-us/library/fh1h056h.aspx
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/rfanetwalk.asp
    Re[2]: Registration-free COM
    От: xhalt Украина  
    Дата: 14.01.06 10:27
    Оценка:
    Здравствуйте, Юнусов Булат, Вы писали:

    ЮБ>http://msdn2.microsoft.com/en-us/library/fh1h056h.aspx

    ЮБ>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/rfanetwalk.asp
    Мимо кассы — это работает только на XP.


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re[3]: Registration-free COM
    От: Юнусов Булат Россия  
    Дата: 14.01.06 11:00
    Оценка:
    Здравствуйте, xhalt, Вы писали:

    X>Здравствуйте, Юнусов Булат, Вы писали:


    ЮБ>>http://msdn2.microsoft.com/en-us/library/fh1h056h.aspx

    ЮБ>>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/rfanetwalk.asp
    X>Мимо кассы — это работает только на XP.

    1 Ты хотел сказать в хр и выше наверно?
    2. Ты метаданных в каталоге приложения держать хотел — а тут они в манифесте — имхо оно удобнее, манифест это файлик, в тех осях где Registration-Free COM не работает можно эти метаданные из манифеста вытащить (а в тех где работает так и будет работать)
    Re[4]: Registration-free COM
    От: xhalt Украина  
    Дата: 14.01.06 11:21
    Оценка:
    Здравствуйте, Юнусов Булат, Вы писали:

    X>>Мимо кассы — это работает только на XP

    ЮБ>1 Ты хотел сказать в хр и выше наверно?
    Наверное. Детально не разбирался.
    ЮБ>2. Ты метаданных в каталоге приложения держать хотел — а тут они в ЮБ>манифесте — имхо оно удобнее, манифест это файлик,
    Под "метаданными" я тоже подразумевал нечто вроде файлика в каталоге приложения... Вообще, я некоректно употребил термин "метаданные", но "слово — не воробей"
    ЮБ>в тех осях где Registration-Free COM не работает можно эти метаданные
    ЮБ>из манифеста вытащить (а в тех где работает так и будет работать)
    Да. Такой подход, пожалуй, будет вполне рационален.


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re: Registration-free COM
    От: xhalt Украина  
    Дата: 14.01.06 11:55
    Оценка:
    Я, собственно, почему спрашиваю —
    не хочеться применять грубые мотеды вроде перехвата системных функций.
    Вдруг, найдутся более "честные" варианты решения.


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re[2]: Registration-free COM
    От: Alexey Frolov Беларусь  
    Дата: 16.01.06 10:10
    Оценка:
    Здравствуйте, xhalt, Вы писали:

    X>Я, собственно, почему спрашиваю —

    X>не хочеться применять грубые мотеды вроде перехвата системных функций.
    X>Вдруг, найдутся более "честные" варианты решения.

    Я конечно понимаю, что такой вариант не соответствует требованиям, но позвольте узнать, чем не устраивает глобальная регистрация СОМ-сервера программно в коде инициализации сервера.
    Re[3]: Registration-free COM
    От: Left2 Украина  
    Дата: 16.01.06 10:45
    Оценка:
    AF>Я конечно понимаю, что такой вариант не соответствует требованиям, но позвольте узнать, чем не устраивает глобальная регистрация СОМ-сервера программно в коде инициализации сервера.

    если к этому добавить трюк с ExeName.Exe.Local в каталоге с Exe и разрегистрацию COM-серверов при выходе из приложения — может получиться довольно дешёвое и имхо вполне надёжное решение.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re: Registration-free COM
    От: al Россия  
    Дата: 16.01.06 14:26
    Оценка:
    Имею готовое решение Вашей проблемы. В кратце:

    http://www.rsdn.ru/Forum/Message.aspx?mid=1020492&amp;only=1
    Автор: al
    Дата: 10.02.05


    Могу продать исходники — регистратор (COM-DLL) + улилита "выдирания" регистрационной информации из DLL.


    Re[2]: Registration-free COM
    От: al Россия  
    Дата: 16.01.06 14:37
    Оценка:
    Более внимательно прочитал начальное сообщение и понял, что предложил не совсем то, что надо.

    > упрощение развертывания (включая возможность запуска приложений непосредственно с CD)


    Это работает (для этого и делалось, главным было обойти защиту HKCR для простого пользователя). При этом регистрация происходит намного быстрее, чем вызов DllRegisterServer из DLL.

    > решение известных проблем версионности COM


    +/-

    > обеспечение возможности одновременной работы с различными версиями ActiveX но с одинаковыми GUID-ами коклассов или progid.


    Возможно только на XP ранее описанным способом. "Ломать" CoCreateInstance не советую.

    PS. Без регистрации в реесте библиотеки типов не будте работать стандарная реализация IDispatch из Ole32.dll. Ее точно использует реализация IDispatchImp из ATL и, (возможно) VB.

    PPS. Т.к. до Win2000 таких фокусов с реестром было делать нельзя, то в Win9x и NT4 регистация выполняется прямой записью данных в HKCR. "Выдиралка" работает только в Win2000/XP.


    Re[3]: Registration-free COM
    От: xhalt Украина  
    Дата: 17.01.06 22:42
    Оценка:
    Здравствуйте, al, Вы писали:

    >> обеспечение возможности одновременной работы с различными версиями ActiveX но с одинаковыми GUID-ами

    >> коклассов или progid.
    >Возможно только на XP ранее описанным способом.

    >"Ломать" CoCreateInstance не советую.

    >PS. Без регистрации в реесте библиотеки типов не будте работать стандарная реализация IDispatch из
    > Ole32.dll. Ее точно использует реализация IDispatchImp из ATL и, (возможно) VB.
    Угу. Теоретические исследования и практические эксперименты показали что
    в тривиальных случаях всё работает как и ожидается, однако при "лобовом" решении:
    — имеются проблемы с typelib-маршалером
    — имеются проблемы с созданием proxy/stub (если они в отдельной DLL)
    — игнорируется ThreadingModel (не выполняется "проксирование" фабрики классов при несоответсвии аппартмента)
    (могут быть неожиданные проблемы с синхронизацией с компонентами с apartment-моделью)
    (К слову: в Wine и ReactOS ThreadingModel тоже игнорируется)

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

    >PPS. Т.к. до Win2000 таких фокусов с реестром было делать нельзя, то в Win9x и NT4 регистация выполняется

    >прямой записью данных в HKCR. "Выдиралка" работает только в Win2000/XP.

    Кстати, моя "выдиралка", которая предназначена для сохранения регистрационной информации (названную в оригинальном посте "метаданными") работает тоже по такому принципу (RegOverridePredefKey).


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re[3]: Registration-free COM
    От: xhalt Украина  
    Дата: 17.01.06 22:57
    Оценка:
    Здравствуйте, Alexey Frolov, Вы писали:

    AF>Здравствуйте, xhalt, Вы писали:


    X>>Я, собственно, почему спрашиваю —

    X>>не хочеться применять грубые мотеды вроде перехвата системных функций.
    X>>Вдруг, найдутся более "честные" варианты решения.

    AF>Я конечно понимаю, что такой вариант не соответствует требованиям,

    На то оно и обсуждение
    AF>но позвольте узнать, чем не устраивает глобальная регистрация СОМ-сервера
    AF>программно в коде инициализации сервера.
    Собственно не устраивает сама _глобальность_ регистрации. Если бы можно было бы регистрировать локально для приложения (например для текущего сенаса запуска) — было бы то что нужно.

    С "глобальность" не совместим use-case с развертыванием DLL внутри каталога exe-приложения (xcopy-, ClickOnce-, и т.п. deployment),
    при наличии двух инсталляций (разных) программных продуктов использующих ком-объект с одинаковым CLSID.
    Особенно актуально при использовании компонент сторонних производителей (которых нельзя или сложно изменять)

    Это и подрузумевалось в оригинальном посте: "обеспечение возможности одновременной работы с различными версиями ActiveX но с одинаковыми GUID-ами коклассов или progid"

    Иными словами, COM (по крайней мере до Windows XP) ограничивает выбор программиста,
    не давая возможности инсталлировать депендсы приложения изолированно, т.е. исключая какое-либо влияние на другие приложения.


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re[4]: Registration-free COM
    От: al Россия  
    Дата: 18.01.06 08:31
    Оценка:
    X>В данный момент разрабатываю чуть иную стратегию, которую изложу здесь чуть позже.


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

    1) Мои задачи решилисть протой запсью в HKCU\Software\Classes

    2) Перехват API-функций, с моей точки зрения — хак, требующий достаточно сложной реализации, отладки и сопровождения.


    Re[4]: Registration-free COM
    От: Left2 Украина  
    Дата: 18.01.06 10:18
    Оценка:
    X>С "глобальность" не совместим use-case с развертыванием DLL внутри каталога exe-приложения (xcopy-, ClickOnce-, и т.п. deployment),
    X>при наличии двух инсталляций (разных) программных продуктов использующих ком-объект с одинаковым CLSID.
    X>Особенно актуально при использовании компонент сторонних производителей (которых нельзя или сложно изменять)

    Всё это решается с помощью трюка с MyFile.Exe.Local — он работает начиная с Win98, то бишь на всех поддерживаемых сейчас WIndows-платформах
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[5]: Registration-free COM
    От: xhalt Украина  
    Дата: 18.01.06 20:19
    Оценка:
    Здравствуйте, al, Вы писали:

    X>>В данный момент разрабатываю чуть иную стратегию, которую изложу здесь чуть позже.


    al>Я в свое время думал о перехвате API-функций работы с реестром — в этом случае можно каждому

    al>процессу "подсунуть" "виртуальный реестр" с нужными нам данными рпеистрации.
    al>Я думаю, что этот путь полностью решит все Ваши задачи...
    Ага. Вот фактически я к этому и пришёл.

    Резюмируя всё вышесказанное — имеем такую вот стратегию:

    1. В каталог нашего приложения our.exe
    размещаем файл-флаг our.exe.Local
    и файл манифест our.exe.manifest, в последний помещаем информацию о регистрации компонент
    как это указано здесь.

    2. Во начале работы приложения (перед началом использования COM-компонент),
    выполняем проверку операционной системы и если она поддерживает registration-free COM — то на этом и останавливаемся

    3. Выполняем перехват API-функций работы с реестром локально для текущего процесса. Подсовываем, как сказал al,
    "виртуальный реестр" с нужными нам данными. Учитывая, что API-функции работы с реестром часто используемы, следует использовать методику перехвата, которая даёт минимально возможное замедление, и, скорее всего, какую-либо разновидность хеш-поиска для проверки принадлежности запрашиваемых ключей/значений к множеству наших.

    Ничего не забыл?


    >1) Мои задачи решились протой запсью в HKCU\Software\Classes

    Если для решения определённой задачи можно ограничиться этим — то несомненно, так и нужно поступить

    >2) Перехват API-функций, с моей точки зрения — хак, требующий достаточно сложной реализации,

    >отладки и сопровождения.
    Я отношусь к таким хакам как к решениям, к которым следует прибегать лишь в крайних случаях (когда ничего другого не остаётся).
    Как вариант, можно восползоваться готовыми и уже проверенными решениями (например, Detours).
    Кстати, в данном конкретном случае, не исключено, что можно ограничиться простой корректировкой
    таблиуы импорта ole32.dll


    Предлагаю работу в Киеве
    Автор:
    Дата: 04.05.06
    Re[6]: Registration-free COM
    От: Odi$$ey Россия http://malgarr.blogspot.com/
    Дата: 19.01.06 04:30
    Оценка:
    Здравствуйте, xhalt, Вы писали:

    X>Резюмируя всё вышесказанное — имеем такую вот стратегию:


    X>1. В каталог нашего приложения our.exe

    X>размещаем файл-флаг our.exe.Local
    X>и файл манифест our.exe.manifest...

    Dynamic-Link Library Redirection:

    If the application has a manifest, then any .local files are ignored.


    + еще всякие непонятные заморочки — Re[9]: manifest, GetModuleHandle и msxml3.dll
    Автор: Odi$$ey
    Дата: 22.08.05
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.