Как сегодня поступать с ActiveX / OCX - таблица решений: оставить, обернуть или заменить

· · COM, ActiveX, OCX, .NET, Разработка Windows, Модернизация

Проекты, в которых всплывают слова ActiveX / OCX, обычно окутаны немного тяжёлой атмосферой.

  • VB6 или старые приложения на C++ / MFC всё ещё в строю
  • SDK промышленного оборудования или измерительных приборов поставляется только в виде OCX
  • Внутренний веб-портал завязан на ActiveX и не может вырваться из IE-режима
  • Хочется перейти с 32 бит на 64, но один-единственный OCX мотает головой

Впрочем, и «выбросить всё, потому что это старое», и «сохранить навечно, потому что оно работает» — одинаково небрежные подходы. Главное — определить, является ли этот ActiveX / OCX простым UI-компонентом или же это граница, вобравшая в себя бизнес-логику и спецификации оборудования.

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

В качестве примеров рассматриваются такие случаи:

  • существующие десктопные приложения на VB6 / MFC / WinForms;
  • поэтапный переход на C# / .NET;
  • устаревшие экраны с WebBrowser / IE-режимом;
  • Windows-приложения с ActiveX-компонентами от сторонних вендоров.

Содержание

  1. Сначала вывод (в двух словах)
  2. Что в этой статье понимается под ActiveX / OCX
  3. Таблица решений, с которой стоит начать
    • 3.1. Общая картина
    • 3.2. Решение оставить
    • 3.3. Решение обернуть
    • 3.4. Решение заменить
    • 3.5. Зависимость от браузера рассматриваем отдельно
  4. Моменты, которые легко сбивают с толку
    • 4.1. UI-компонент или компонент, несущий спецификацию
    • 4.2. 32-бит / 64-бит и границы процессов
    • 4.3. Регистрация, распространение, права, лицензии
    • 4.4. STA / цикл сообщений / обратные вызовы
    • 4.5. Есть ли тесты, можно ли наблюдать за поведением
  5. Рекомендации по типовым сценариям
    • 5.1. Внутреннее десктопное приложение, которое до сих пор стабильно работает
    • 5.2. Хотите перенести 32-битный OCX на 64-битную сторону
    • 5.3. Экраны, завязанные на IE / WebBrowser
    • 5.4. ActiveX с управлением оборудованием или собственной спецификацией
  6. Частые антипаттерны
  7. Чек-лист для начала миграции
  8. Краткая шпаргалка по выбору
  9. С какими вопросами к нам обращаться
  10. Итог
  11. Список источников

1. Сначала вывод (в двух словах)

  • Увидев ActiveX / OCX, в первую очередь нужно судить не «старое ли это», а что именно взял на себя этот компонент
  • Если это простой UI-компонент, заменить его сравнительно легко
  • Если он несёт управление оборудованием, отчёты, собственный формат файлов или многолетние особенности эксплуатации, безопаснее сначала обернуть его, а не сразу переписывать заново
  • Если он стабильно работает на десктопе и область изменений невелика, решение оставить как есть вполне обосновано
  • У зависимости от ActiveX в браузере продлить жизнь можно, но будущее у неё узкое, так что здесь стоит смотреть на замену как на приоритет
  • 32-битный OCX нельзя напрямую загрузить в 64-битный процесс. Силой воли эту границу не перепрыгнуть
  • Регистрация, зависимые DLL, права администратора, лицензии, STA / MTA — трения вне самой реализации часто становятся самым сложным местом
  • И «переписать всё заново на всякий случай», и «заморозить навсегда из страха» — варианты с высокой аварийностью

Иначе говоря, порядок принятия решения такой.

  1. Что несёт в себе этот OCX
  2. Обязательно ли использовать его в том же процессе
  3. Не застрянете ли вы на 32-бит / 64-бит, регистрации или зависимости от браузера
  4. Стоит ли сначала создать тестируемую границу, а потом уже заменять

При таком порядке разобраться получается значительно проще.

2. Что в этой статье понимается под ActiveX / OCX

Сначала зафиксируем, как в этой статье используются термины.

Термин Значение в этой статье
COM Бинарно-совместимая компонентная модель Windows. Основа публичных интерфейсов, регистрации, Apartment Model и так далее
ActiveX / OCX На практике этими словами часто обозначают в совокупности COM-компоненты и связанные с ними активы. В частности, сюда часто относят UI-элементы управления .ocx и компоненты, встраиваемые в IE или контейнеры
Зависимость от WebBrowser / IE Даже если это не сам ActiveX, сюда относятся встроенные браузеры и интеграции, построенные на «мировоззрении IE». С точки зрения принятия решений это очень похожая проблема

Строго говоря, ActiveX и COM — не одно и то же. Но на практике проблемные точки у них весьма похожи.

  • Совпадают ли 32-бит / 64-бит
  • Как распространять регистрацию и зависимые DLL
  • В каком хосте / контейнере это работает
  • Не застрянете ли вы на STA, цикле сообщений, обратных вызовах
  • Не осталась ли зависимость от браузера

В этой статье мы рассматриваем такие практические точки принятия решений в комплексе.

3. Таблица решений, с которой стоит начать

3.1. Общая картина

Если начать с этой таблицы, общее направление, как правило, определяется сразу.

Ситуация Первый выбор Причина
Есть зависимость от ActiveX в браузере Склоняемся к замене Сам Edge не поддерживает ActiveX, а IE-режим позиционируется как мера продления жизни
OCX стабильно работает в десктопном приложении, область изменений невелика Склоняемся к тому, чтобы оставить Стоимость слома сейчас часто выше
Хочется перевести на .NET только окружение, но поведение компонента непредсказуемо Склоняемся к обёртыванию Безопаснее сначала навести порядок на границе
Хотите поместить 32-битный OCX напрямую в 64-битный процесс Обернуть / изменить конфигурацию Это граница, которую нельзя пересечь in-proc
Используется только как UI-компонент, есть замена Склоняемся к замене Часто достаточно поверхностной замены
Вендор прекратил поддержку, постоянные проблемы с подписью, регистрацией, зависимыми DLL Склоняемся к замене Эксплуатационные издержки уже проявились как технический долг
Внутри — управление оборудованием, отчёты, собственный протокол Склоняемся к обёртыванию Пока поведение не зафиксировано, стоимость замены непредсказуема
ДаНетДаДаНетНетДаНетДаНетЕсть ActiveX / OCXЗависимость от браузера?Приоритет — заменаIE-режим — мера продления жизниВ основном UI-компонент?Есть равноценная замена?Рассмотреть заменуСначала обернуть и навести порядок на границеЕсть управление оборудованием / своя спецификация / логика отчётов?Сначала обернутьсобрать тесты, затем заменять поэтапноБольно с регистрацией / разрядностью / распространением?Пересмотреть конфигурациюрассмотреть out-of-proc / связь через отдельный процесс / Reg-Free COMРешение оставить тоже реалистично

Далее рассмотрим каждый вариант по порядку.

3.2. Решение оставить

Сам по себе факт, что это ActiveX / OCX, ещё не делает его объектом замены. При соблюдении следующих условий оставить его как есть чаще всего действительно дешевле всего.

  • Область использования замкнута, а условия эксплуатации зафиксированы — внутреннее распространение, поставка вместе с оборудованием и тому подобное
  • Этот компонент до сих пор стабильно работает, и запросы на изменение невелики
  • Вендор всё ещё активен, либо компания может обеспечить хотя бы минимальную поддержку своими силами
  • Нет зависимости от браузера — всё замкнуто на существующем десктопном хосте
  • Предпосылку о 32-бит / 64-бит пока менять не нужно

Здесь важно понимать: оставить — не значит забросить. Если вы оставляете компонент, стоит сделать как минимум следующее.

  • Задокументировать поддерживаемую ОС, разрядность, необходимые зависимые DLL и порядок регистрации
  • Перевести установку, регистрацию и удаление со «человеческих» заметок на скрипты или инсталлятор
  • Подготовить дымовой тест (smoke test) для чистого окружения
  • По возможности собрать все обращения к компоненту в одном месте, а не разбрасывать по всему приложению

Хуже всего — 10 лет подряд следовать принципу «работает — не трогай», пока никто уже не сможет объяснить исходные предпосылки. Чем чаще вы выбираете оставить компонент, тем важнее становится сделать эти предпосылки видимыми.

3.3. Решение обернуть

На практике именно этот выбор отнимает больше всего работы.

«Обернуть» здесь означает изолировать ActiveX / OCX внутри узкой границы и представить его окружению как новый API или новый экранный компонент.

Это довольно эффективно. Причина в том, что если начать полную переработку на этапе, когда поведение старого компонента ещё не разгадано до конца, легко получить двойную муку — раскопки спецификации и воспроизведение дефектов одновременно. Безопаснее сначала изолировать старый компонент и навести порядок только на границе.

У обёртывания есть несколько устоявшихся форм.

Способ обёртывания Подходит для На что обратить внимание
Хост на WinForms + AxHost / Aximp Встраивание в существующие десктопные экраны, когда нужно оставить лишь несколько экранов STA, события, зависимости времени дизайна, лицензирование
32-битный вспомогательный EXE / COM LocalServer / связь через отдельный процесс Переход на 64-битную сторону, изоляция сбоев Межпроцессное взаимодействие, порядок запуска, мониторинг, развёртывание
COM-совместимый фасад на стороне .NET Обновление внутренней реализации при сохранении существующих вызывающих COM-кода IID / CLSID / TLB / способ регистрации / разрядность

Особенно важно при обёртывании не копировать старый API целиком, все 200 методов подряд. Если так сделать, вы просто перенесёте старые особенности прямо в новый код без изменений.

При обёртывании заметно помогает учитывать следующее.

  • Использовать методы крупной зернистости
  • Не давать экранному коду напрямую трогать OCX
  • Фиксировать на границе логи, необходимые при сбое
  • Определить на границе ответственность за тайм-ауты, повторные попытки и преобразование исключений
  • Сделать так, чтобы будущую замену можно было подставить через тот же интерфейс

Иногда на новой стороне .NET хочется сохранить только входную точку COM. В этом случае реалистична конфигурация «обновляем содержимое, но сохраняем только COM-контракт». Однако ощущений эпохи .NET Framework, когда достаточно было «на всякий случай сделать RegAsm», может не хватить. Работу с современным COM host в .NET, TLB, разрядностью и Registry-Free COM лучше спроектировать заранее — потом будет проще.

3.4. Решение заменить

Замена подходит главным образом для случаев, когда проблема — это поверхностное устаревание.

В таких ситуациях лучше рассматривать замену как приоритет.

  • Этот ActiveX используется только как UI-компонент
  • Вендор выпустил преемника для .NET / WPF / WebView2
  • Тормозит зависимость от браузера или предпосылка про IE
  • Постоянные проблемы с регистрацией, подписью, правами администратора, настройками безопасности
  • Есть тесты или бизнес-сценарии, позволяющие проверить альтернативную реализацию

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

Если вы заменяете, начинайте с UI.

  • Сетки (grid)
  • Календари
  • Деревья
  • Область отображения браузера
  • Простые вспомогательные элементы ввода

Их сравнительно легко заменить. С другой стороны, встречаются и такие, что выглядят как UI, а внутри плотно набиты логикой.

  • ActiveX от вендора для управления оборудованием
  • Элементы управления, слитые с печатью или формированием отчётов
  • Элементы управления, инкапсулирующие чтение и запись собственного формата файлов
  • Элементы управления с COM-обратными вызовами или предпосылками о потоках

Ошибитесь в этом различии — и оценка трудозатрат рассыплется в одночасье.

3.5. Зависимость от браузера рассматриваем отдельно

Это действительно отдельная категория.

У ActiveX в браузере, в отличие от десктопного OCX, довольно слабые основания для дальнейшего развития.

Причина проста: современные браузерные платформы больше не делают это своим главным полем боя. Сам Microsoft Edge не поддерживает ActiveX. IE-режим, в свою очередь, использует движок семейства IE для настроенных сайтов и может служить слоем совместимости для запуска части функций IE, включая ActiveX.

Иными словами:

  • Продлить жизнь, чтобы оно работало сейчас, — можно
  • Но как долгосрочное проектное решение будущее у него не широкое

То же самое происходит и с элементом управления WebBrowser, встроенным в Windows-приложения. WebBrowser тянет за собой мировоззрение IE, поэтому если нужно просто отображать HTML, для новой работы естественнее сделать первым кандидатом WebView2.

Однако здесь важно учитывать: WebView2 — не полная замена WebBrowser «один в один».

  • Скрипты, рассчитанные на DOM IE
  • Зависимости от ActiveX
  • Допущения вокруг window.external
  • Поведение, завязанное на зоны безопасности и интранет

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

4. Моменты, которые легко сбивают с толку

4.1. UI-компонент или компонент, несущий спецификацию

Это самое важное.

Для старой сетки или календаря достаточно проверить совместимость внешнего вида и событий — и разговор заметно продвигается. С другой стороны, у ActiveX с управлением оборудованием, отчётами или собственным форматом за внешним видом скрывается целый ком спецификаций.

Хотя это выглядит как один и тот же «элемент управления на экране», на деле диапазон довольно широк.

  • Простой компонент отображения списка
  • Компонент, посылающий команды оборудованию по собственному протоколу
  • Компонент, который внутри самостоятельно занимается тайм-аутами, переподключением, повторной отправкой и поглощением исключений
  • Компонент, несущий на себе совместимость печати или форматов экспорта

Переписывать последний вариант заново с нуля — как правило, это превращается в проект по раскопке спецификации. Здесь безопаснее сначала обернуть компонент.

4.2. 32-бит / 64-бит и границы процессов

Это часто упускают из виду, хотя по сути это очень важный момент.

In-proc OCX должен совпадать по разрядности с процессом, который его загружает. То есть 32-битный OCX нельзя напрямую загрузить в 64-битное приложение.

Реалистичные варианты здесь, как правило, сводятся к трём.

  • Пока оставить хост-приложение тоже 32-битным
  • Изолировать OCX в отдельном 32-битном процессе и связать его с 64-битной стороной через IPC или out-of-proc COM
  • Заменять зависимость от этого OCX, начиная с тех мест, где это возможно

Расчёт «раз Any CPU, то как-нибудь само образуется» здесь обычно не работает. Даже если вы создаёте COM-совместимый фасад на новой стороне .NET, внешний вид managed-кода и фактическая разрядность COM host — это разные вопросы. Начните здесь небрежно — и получите неприятную ситуацию, когда сборка проходит, а на машине заказчика ничего не запускается.

4.3. Регистрация, распространение, права, лицензии

Технически компонент вызывается без проблем, а вот на этапе распространения всё умирает. Для ActiveX / OCX это довольно частая история.

Обычно проблемными местами становятся такие вещи.

  • Предпосылки для regsvr32 держатся только в чьей-то голове
  • Размещение зависимых DLL нигде явно не зафиксировано
  • Нужны права администратора, но это не отражено в порядке эксплуатации
  • У вендорского компонента разделены лицензии design-time и runtime
  • Работает на машине разработчика, но не работает в чистом окружении

Всё это способно остановить проект, даже если не тронуть ни строчки кода.

Конфигурации без регистрации или размещение side-by-side иногда облегчают ситуацию, но это не волшебный порошок — совместимость с контейнером и способом распространения всё равно нужно проверять.

Иными словами, миграция ActiveX / OCX — это не только реализация, но и проектирование распространения. Отложите этот момент на потом — и в конце вас ждёт эффектное падение.

4.4. STA / цикл сообщений / обратные вызовы

ActiveX / OCX — это не просто вызов DLL. Он может нести предпосылки о потоковой модели COM и о цикле сообщений.

Особенно стоит насторожиться в таких случаях:

  • Стабильность обеспечивается только при работе в UI-потоке
  • Компонент рассчитан на STA, но его небрежно вызывают со стороны MTA
  • Во время синхронного вызова возвращается обратный вызов (callback)
  • Неясно, в каком потоке должны приниматься события

Поначалу это проявляется в виде «страшилок» — «иногда зависает», «иногда не приходят события». Но по сути это почти всегда нарушение предпосылок.

Поэтому и при обёртывании, и при замене лучше заранее зафиксировать, в каком потоке создавать объект, из какого потока вызывать и где принимать события.

4.5. Есть ли тесты, можно ли наблюдать за поведением

Заменить компонент трудно не только потому, что код старый. Трудно потому, что нет критерия, по которому можно сказать «поведение осталось тем же».

Одно только наличие следующего сильно меняет дело.

  • Дымовые тесты для каждого сценария работы
  • Примеры входных и выходных данных
  • Снимки экрана или образцы отчётов
  • Шаблоны ошибок и ожидаемое поведение
  • Логи на случай тайм-аута или отсутствия подключённого оборудования

Особенно когда задействовано оборудование или отчёты, случается странная вещь: реальное поведение оказывается более правдивым источником, чем спецификация. Без средств наблюдения замена превращается в раскопки.

5. Рекомендации по типовым сценариям

5.1. Внутреннее десктопное приложение, которое до сих пор стабильно работает

Рекомендация — склоняться к тому, чтобы оставить.

При таких условиях часто лучше не отдирать компонент насильно.

  • Используется только внутри компании
  • Целевые устройства и ОС в достаточной мере зафиксированы
  • Этот OCX задействован лишь на нескольких экранах
  • Запросы на доработку невелики, срок жизни предсказуем

Тем не менее лучше не оставлять компонент «голым» как есть, а хотя бы собрать места вызова в одном месте — это окупится позже.

Иначе говоря, стратегия такая:

  • Сейчас — оставить
  • Но навести порядок хотя бы на границе
  • Сделать так, чтобы, когда потребуется замена, можно было начать именно отсюда

Такая трёхступенчатая структура выглядит естественно.

5.2. Хотите перенести 32-битный OCX на 64-битную сторону

Рекомендация — обернуть / изменить конфигурацию.

Идти здесь напролом — тупик: 32-битный OCX нельзя загрузить in-proc в 64-битный процесс.

Реалистично управлять этим удобнее, изолировав компонент во вспомогательном 32-битном процессе или LocalServer и общаясь с 64-битным приложением через грубый (coarse) API.

32-битный OCX32-битный хелпер / LocalServer64-битное .NET-приложение32-битный OCX32-битный хелпер / LocalServer64-битное .NET-приложениеЗапрос через грубый APIIn-proc вызовРезультат / событияПреобразованный результат

Здесь важно не транслировать все мелкие методы напрямую один в один. Межпроцессная граница быстро становится болезненной, если прогонять через неё большой поток мелких вызовов.

  • Стремитесь к зернистости примерно «1 операция = 1 запрос»
  • Приводите возвращаемые значения и ошибки к осмысленным единицам
  • Фиксируйте логи на границе

При такой форме позже, когда потребуется по-настоящему заменить внутреннюю реализацию, это тоже будет проще.

5.3. Экраны, завязанные на IE / WebBrowser

Рекомендация — приоритет замены.

Это область, где «работает сейчас» и «легко поддерживать в дальнейшем» плохо совпадают. IE-режим сильно помогает с совместимостью, но предпосылка всё равно остаётся связанной с семейством IE.

Поэтому удобно разделить подход так:

  • Продлевать жизнь через IE-режим, чтобы не останавливать внутренние процессы
  • При этом не путать продление жизни с постоянным решением
  • Выбирать замену из WebView2, чистого веба, гибрида нативного UI и веба и подобных вариантов

Особенно если элемент управления WebBrowser используется просто как HTML-вьюер, приоритет замены высокий.

С другой стороны, если ActiveX внутри браузера выполняет ещё и роли вроде работы с локальными файлами, оборудованием, подписью или собственными надстройками, это уже не замена движка рендеринга, а переработка нативной интеграции. Здесь разговор становится немного тяжелее.

5.4. ActiveX с управлением оборудованием или собственной спецификацией

Рекомендация — сначала обернуть.

Этот тип содержательнее, чем кажется по внешнему виду. Даже если документация SDK скудная, за годы работы в реальных условиях в компоненте могло неявно накопиться поведение вроде такого:

  • Как он ждёт при неудачном подключении
  • Повторные попытки после тайм-аута
  • Порядок событий
  • Обходные пути, поглощающие особенности реального оборудования
  • Интерпретация исключений и кодов ошибок

Если переписывать такой компонент заново, руководствуясь принципом «он всё равно старый», с высокой вероятностью загорятся полевые испытания.

Поэтому безопаснее начинать именно отсюда.

  1. Изолировать существующий компонент внутри границы
  2. Добавить логирование, чтобы было видно, что происходит
  3. Собрать тестовые сценарии и шаблоны поведения реального оборудования
  4. И только затем выделить те участки, которые можно заменить

Это не эффектно, но на практике именно это работает лучше всего.

6. Частые антипаттерны

Антипаттерн В чём боль Первый шаг к исправлению
Полная переработка только потому, что есть ActiveX Легко упустить часть спецификации и получить взрыв трудозатрат Сначала инвентаризация и выделение границ
Попытка напрямую поместить 32-битный OCX в 64-битное приложение Принципиально невозможно Изолировать на 32-битной стороне или изменить конфигурацию
Прямые вызовы API компонента из экранного кода Легко становится невозможно заменить Свести к адаптеру / фасаду
Ручная эксплуатация процедуры regsvr32 Различия окружений вызывают сбои каждый раз Рассмотреть инсталлятор, скрипты, манифесты
Успокоенность из-за наличия IE-режима Легко перепутать продление жизни с постоянным решением Определить план замены и условия завершения
Поведение не зафиксировано перед заменой Невозможно судить о завершённости Подготовить дымовые тесты, тестовые данные, логи

Из них на практике особенно часто встречаются три.

  1. Спешка с полной переработкой
  2. Недооценка барьера разрядности
  3. Разбрасывание API по всему приложению

Избегая всего этих трёх пунктов, вы уже заметно снижаете аварийность.

7. Чек-лист для начала миграции

Проекты с ActiveX / OCX идут лучше, если сначала провести инвентаризацию, а не сразу бросаться в реализацию. Порядок примерно такой.

  1. Составить перечень используемых OCX / DLL
    • Имя файла, версия, ProgID, CLSID, вендор, наличие лицензии
  2. Выяснить, где они используются
    • Экраны, функции, отчёты, оборудование, пакетные задания, интеграция с Office и так далее
  3. Проверить разрядность и условия хоста
    • 32-бит / 64-бит, in-proc / out-of-proc, предпосылка STA, зависимость от браузера
  4. Проверить условия распространения
    • Способ регистрации, зависимые DLL, права администратора, тихая установка, воспроизведение в чистом окружении
  5. Создать дымовые тесты
    • Не только штатный сценарий, но и сбои, отсутствие подключения, тайм-ауты
  6. Построить границу
    • Адаптер, сервис, фасад, связь через отдельный процесс и так далее
  7. Опробовать на малых единицах — один экран, одна функция, одно устройство
  8. Расширять от границ, которые сработали, постепенно применяя оставить / обернуть / заменить

Пропустите эти шаги — и потом будет сложно объяснить даже то, что именно оказалось трудным.

8. Краткая шпаргалка по выбору

Ситуация Первый выбор
Стабильно работает только внутри компании, изменения невелики Оставить
Хочется перевести на .NET только окружение Обернуть
Сталкиваются 32-бит / 64-бит Обернуть / изменить конфигурацию
Зависимость от IE / WebBrowser / ActiveX в браузере Заменить
Простой UI-компонент, есть замена Заменить
Несёт управление оборудованием, отчёты, собственную спецификацию Обернуть
Постоянные проблемы с регистрацией или распространением Обернуть или заменить

Если сомневаетесь, для начала определите, UI-компонент это или граница, несущая спецификацию, — так вы вряд ли ошибётесь.

9. С какими вопросами к нам обращаться

Эта тема часто приносит пользу уже на этапе прояснения направления, ещё до начала самой разработки.

Например, к нам хорошо подходят такие запросы:

  • Хотите провести инвентаризацию и понять, какие OCX действительно нужно заменить
  • Хотите заранее разобраться только с узкими местами 32-бит / 64-бит
  • Хотите перейти на .NET, но сохранить только входную точку COM
  • Хотите сравнить меры продления жизни и стратегию отступления для ActiveX, поддержку которого прекратил вендор
  • Хотите увидеть, с какого места можно начать отделять зависимость от IE / WebBrowser
  • Хотите для начала безопасно выделить только один экран или одну функцию

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

10. Итог

Как поступать с ActiveX / OCX — это не вопрос, который решается фразой «это легаси, поэтому плохо».

Есть четыре момента, на которые стоит смотреть в первую очередь.

  1. Это простой UI-компонент или граница, несущая спецификацию
  2. Обязательно ли использовать его в том же процессе
  3. Не застрянете ли вы на 32-бит / 64-бит, регистрации, зависимости от браузера или лицензировании
  4. Можно ли наблюдать за поведением до замены

Когда эти четыре момента прояснены, картина обычно складывается так:

  • Стабильно работает, срок жизни предсказуем — оставить
  • Хочется модернизировать только окружение — обернуть
  • UI-компонент или зависимость от браузера — заменить
  • Компонент, несущий ком спецификаций, — сначала обернуть, затем заменять поэтапно

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

Когда вы научитесь совмещать в своём мышлении «оставить, обернуть, заменить», проекты с ActiveX / OCX внезапно превращаются в решаемую задачу.

11. Список источников

  • Microsoft Learn: AxHost Class (System.Windows.Forms)
    • https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.axhost
  • Microsoft Learn: Aximp.exe (Windows Forms ActiveX Control Importer)
    • https://learn.microsoft.com/ja-jp/dotnet/framework/tools/aximp-exe-windows-forms-activex-control-importer
  • Microsoft Learn: How to: Add ActiveX Controls to Windows Forms
    • https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-add-activex-controls-to-windows-forms
  • Microsoft Learn: Expose .NET Core components to COM
    • https://learn.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com
  • Microsoft Learn: Registration-Free COM Interop
    • https://learn.microsoft.com/en-us/dotnet/framework/interop/registration-free-com-interop
  • Microsoft Learn: Frequently Asked Questions about Microsoft Edge
    • https://learn.microsoft.com/ja-jp/deployedge/microsoft-edge-frequently-asked-questions
  • Microsoft Learn: What is Internet Explorer (IE) mode?
    • https://learn.microsoft.com/en-us/deployedge/edge-ie-mode
  • Microsoft Learn: WebBrowser Class (System.Windows.Forms)
    • https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser
  • Microsoft Learn: Introduction to Microsoft Edge WebView2
    • https://learn.microsoft.com/en-us/microsoft-edge/webview2/
  • KomuraSoft Blog: Основы, как избежать зависаний при STA/MTA в COM
    • https://comcomponent.com/ru/blog/2026/01/31/000-sta-mta-com-relationship/
  • KomuraSoft Blog: Почему при использовании нативных DLL на C++ из C# стоит делать обёртку на C++/CLI
    • https://comcomponent.com/ru/blog/2026/03/07/000-cpp-cli-wrapper-for-native-dlls/
  • KomuraSoft Blog: Пример из практики, где помогает мост COM - вызов 64-битной DLL из 32-битного приложения
    • https://comcomponent.com/ru/blog/2026/01/25/002-com-case-study-32bit-to-64bit/

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

Статья напрямую связана со следующими услугами.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Стоит ли заменять ActiveX / OCX?
Решение принимается не по признаку «старое или нет», а исходя из того, что именно взял на себя этот компонент. Если это простой UI-компонент и есть замена — заменяйте; если он несёт управление оборудованием, отчёты или собственный формат файлов — сначала оберните его и наведите порядок на границе; а если он стабильно работает и область изменений невелика, решение оставить как есть тоже вполне реалистично. И «переписать всё заново на всякий случай», и «заморозить навсегда из страха» — оба варианта с высокой вероятностью аварий.
Можно ли использовать 32-битный OCX из 64-битного приложения?
В in-process режиме — нет. OCX должен совпадать по разрядности с процессом, который его загружает, и это принципиальное ограничение. Реалистичные варианты таковы: пока оставить хост-приложение тоже 32-битным; изолировать OCX в отдельном 32-битном процессе (вспомогательном EXE или COM LocalServer) и связать его с 64-битной стороной через IPC или out-of-proc COM; либо заменять зависимость от OCX, начиная с тех мест, где это возможно.
Что делать с зависимостью от ActiveX в браузере?
Здесь стоит смотреть на замену как на приоритет. Сам Microsoft Edge не поддерживает ActiveX, а IE-режим позиционируется как мера продления жизни. Элемент управления WebBrowser точно так же тянет за собой мировоззрение IE, поэтому если нужно просто отображать HTML, первым кандидатом становится WebView2. Однако WebView2 — не полная замена «один в один»: скрипты, рассчитанные на DOM IE, и допущения вокруг window.external напрямую не переносятся.
Что конкретно означает «обернуть» ActiveX / OCX?
Это означает изолировать ActiveX / OCX внутри узкой границы и представить его окружению как новый API или новый экранный компонент. Есть несколько устоявшихся форм: хост на WinForms + AxHost, связь через отдельный процесс с помощью 32-битного вспомогательного EXE или LocalServer, COM-совместимый фасад на стороне .NET. При обёртывании не копируйте старый API целиком в большом объёме — используйте методы крупной зернистости, закрепите на границе ответственность за логирование, тайм-ауты и преобразование исключений, и сделайте так, чтобы будущую замену можно было подставить через тот же интерфейс.

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог