ActiveX / OCX 现在该如何处理 - 保留、封装、替换的判断表
· 小村 豪 · COM, ActiveX, OCX, .NET, Windows 开发, 现代化改造
一提到 ActiveX / OCX,项目里的气氛通常都会稍微沉重一点。
- VB6 或古老的 C++ / MFC 应用仍在现役
- 工业设备或测量仪器的 SDK 只提供 OCX
- 公司内部网站以 ActiveX 为前提,一直脱不开 IE 模式
- 明明想从 32bit 迁到 64bit,却有一个 OCX 在那里摇头
不过,这里无论是「因为老旧就全部扔掉」,还是「因为还在运行就永久保留」,都太草率了。 真正重要的是分辨出:这个 ActiveX / OCX 究竟只是单纯的 UI 部件,还是承载着业务规格或设备规格的边界面。
本文会按照容易判断的顺序,整理发现 ActiveX / OCX 时, 应该选择 保留、封装、还是替换。
适用的场景,例如:
- VB6 / MFC / WinForms 系列的现有桌面应用
- 向 C# / .NET 的分阶段迁移
- 包含 WebBrowser / IE 模式的旧版界面
- 包含供应商制 ActiveX 控件的 Windows 应用
目录
- 先说结论(一句话)
- 本文所说的 ActiveX / OCX
- 先看判断表
- 3.1. 整体图
- 3.2. 保留的判断
- 3.3. 封装的判断
- 3.4. 替换的判断
- 3.5. 浏览器依赖单独考虑
- 容易搞乱判断的论点
- 4.1. 是 UI 部件,还是承载规格的部件
- 4.2. 32bit / 64bit 与进程边界
- 4.3. 注册、分发、权限、许可
- 4.4. STA / 消息循环 / 回调
- 4.5. 有没有测试、能否观测
- 各类典型场景的建议
- 5.1. 目前仍稳定运行的内部桌面应用
- 5.2. 想把 32bit OCX 搬到 64bit 一侧
- 5.3. IE / WebBrowser 前提的界面
- 5.4. 承载设备控制或专有规格的 ActiveX
- 常见的反模式
- 开始迁移时的检查清单
- 大致的使用区分
- 这类相谈很适合我们
- 总结
- 参考资料
1. 先说结论(一句话)
- 看到 ActiveX / OCX 时,首先要判断的不是「是不是老旧」,而是这个部件承担了什么职责
- 如果只是单纯的 UI 部件,替换相对容易
- 如果承载着设备控制、报表、专有文件格式,或者多年运维形成的习惯,与其立刻重新实现,先封装 会更安全
- 如果在桌面端稳定运行、改动范围很小,保留 也完全是合理的选择
- 浏览器上的 ActiveX 依赖,可以延命,但未来空间很窄,更适合以替换为优先
- 32bit 的 OCX 不能直接加载到 64bit 进程中,这一点无法靠意志力跨越
- 注册、依赖 DLL、管理员权限、许可证、STA / MTA 等实现之外的摩擦,往往才是真正的难点
- 「干脆全面重写」与「因为害怕就永久冻结」,这两种做法出问题的概率都很高
归纳一下,判断的顺序是这样的:
- 这个 OCX 承载着什么
- 是否必须在同一个进程中使用
- 32bit / 64bit、注册、浏览器依赖会不会卡住
- 要不要先建立可测试的边界,再进行替换
按这个顺序看,会明显更容易整理清楚。
2. 本文所说的 ActiveX / OCX
先把本文用词的范围定下来。
| 词语 | 本文中的含义 |
|---|---|
| COM | Windows 的二进制兼容组件模型。公开接口、注册、Apartment Model 等都是它的基础 |
| ActiveX / OCX | 在实务中,经常被用来泛指基于 COM 的控件及其周边资产。尤其常包含 .ocx 形式的 UI 控件,以及嵌入 IE / 容器中的部件 |
| WebBrowser / IE 系依赖 | 即使不是 ActiveX 本身,也包括那些以「IE 的世界观」为前提的嵌入式浏览器或相关联动。在判断上属于相当接近的问题 |
严格来说,ActiveX 和 COM 并不是同一件事。 不过在实务中,遇到麻烦的点相当相似:
- 32bit / 64bit 是否匹配
- 注册和依赖 DLL 如何分发
- 运行在哪个宿主 / 容器中
- 是否会在 STA、消息循环、回调上卡住
- 是否还残留着浏览器依赖
本文会把这些实务上的判断点汇总起来讨论。
3. 先看判断表
3.1. 整体图
先看下面这张表,大致的方针就能定下来。
| 情况 | 首选做法 | 理由 |
|---|---|---|
| 依赖浏览器上的 ActiveX | 偏向替换 | Edge 本体不支持 ActiveX,IE 模式的定位只是延命措施 |
| 桌面应用中 OCX 稳定运行、改动范围小 | 偏向保留 | 现在去动它的成本往往更大 |
| 只想让周边 .NET 化,但控件行为难以摸清 | 偏向封装 | 先整理边界更安全 |
| 想把 32bit OCX 直接放进 64bit 进程 | 封装 / 调整架构 | 这是 in-proc 无法跨越的边界 |
| 只作为 UI 部件使用,且有替代方案 | 偏向替换 | 表面替换往往就够了 |
| 因供应商停止维护、签名、注册、依赖 DLL 而屡屡出事 | 偏向替换 | 运维成本已经表现为技术负债 |
| 内含设备控制、报表、专有协议 | 偏向封装 | 先固定行为,替换成本才能估算清楚 |
flowchart TD
start["存在 ActiveX / OCX"] --> q1{"依赖浏览器?"}
q1 -- "是" --> p1["优先替换<br/>IE 模式只是延命措施"]
q1 -- "否" --> q2{"主要是UI部件?"}
q2 -- "是" --> q3{"有同等替代方案?"}
q3 -- "是" --> p2["考虑替换"]
q3 -- "否" --> p3["先封装并整理边界"]
q2 -- "否" --> q4{"承载设备控制/专有规格/报表逻辑?"}
q4 -- "是" --> p4["先封装<br/>补齐测试后再分阶段替换"]
q4 -- "否" --> q5{"注册/bitness/分发很痛苦?"}
q5 -- "是" --> p5["重新审视架构<br/>考虑 out-of-proc / 跨进程连接 / Reg-Free COM"]
q5 -- "否" --> p6["保留也是现实的选择"]
以下按顺序逐一说明各种情况。
3.2. 保留的判断
不能因为是 ActiveX / OCX 就立刻列为替换对象。只要满足以下条件,保留往往就是成本最低的选择。
- 使用范围是封闭的,公司内部分发或随设备出厂的运行环境是固定的
- 该控件目前仍稳定运行,变更需求不大
- 供应商仍在维护,或自己公司具备最低限度的维护能力
- 不依赖浏览器,在桌面端现有宿主中就能完整闭环
- 32bit / 64bit 的前提暂时不需要改变
这里重要的是,保留 不等于 放任不管。如果选择保留,至少应该做到以下几点:
- 用文档记录支持的 OS、bitness、必需的依赖 DLL、注册步骤
- 把安装、注册、卸载从人工记忆改成脚本或安装程序
- 准备在干净环境下的冒烟测试
- 尽量把对该控件的调用收敛到一处,而不是散落在整个应用中
最糟糕的情况是,「因为还能用就不去动它」持续了 10 年,最后没人能说清楚前提条件是什么。 选择保留的程度越高,让前提可见化 就越重要。
3.3. 封装的判断
在实务中,这个选择往往是工作量最大的部分。
这里所说的「封装」,是指把 ActiveX / OCX 关进一个狭窄的边界内部, 对外则以新的 API 或新的界面部件呈现。
这样做相当有效。 因为如果在旧部件的行为还没摸清楚的阶段就直接进入全面重写,很容易同时陷入「发掘规格」和「重现故障」的双重困境。 先把旧部件隔离起来,只整理边界 会更安全。
封装的方式有几种类型。
| 封装方式 | 适合场景 | 需要关注的点 |
|---|---|---|
| WinForms 宿主 + AxHost / Aximp | 想嵌入现有桌面界面、只想保留少数几个界面 | STA、事件、设计时依赖、许可证 |
| 32bit helper EXE / COM LocalServer / 跨进程桥接 | 想迁向 64bit、想把崩溃隔离开 | 进程间通信、启动顺序、监控、部署 |
| .NET 一侧的 COM 兼容入口 | 想保留现有 COM 调用方,同时更新内部实现 | IID / CLSID / TLB / 注册方式 / bitness |
特别重要的一点是,封装时不要把旧 API 原样复制 200 个。 如果那样做,只是把旧的束缚原样搬进新代码而已。
封装时,注意以下几点会明显改善质量:
- 做成粗粒度的方法
- 不让界面代码直接触碰 OCX
- 在边界处记录失败时所需的日志
- 在边界上明确超时、重试、异常转换的职责
- 让未来的替代实现也能用同一个接口换入
有时也会希望在新的 .NET 一侧只保留 COM 入口。 这种情况下,「内部实现更新,但 COM 契约保持不变」是一种现实的架构。 不过,用 .NET Framework 时代的感觉认为「先 RegAsm 一下就行」未必成立。 现在 .NET 的 COM host、TLB、bitness、Registry-Free COM 的处理方式,最好提前设计清楚,后面会省不少事。
3.4. 替换的判断
适合替换的,主要是 表面的老旧 成为问题的场景。
以下情况更适合优先替换:
- 该 ActiveX 只是作为 UI 部件使用
- 供应商已经推出面向 .NET / WPF / WebView2 的后继产品
- 浏览器依赖或 IE 前提拖了后腿
- 注册、签名、管理员权限、安全设置每次都会出问题
- 已经有可以验证替代实现的测试或业务场景
反过来,仅仅因为「看起来老旧」,就把承载着设备控制或报表逻辑的部件一口气丢掉,通常会变成一场泥潭。
如果要替换,应该从 UI 开始:
- 表格
- 日历
- 树形控件
- 浏览器显示部分
- 简单的输入辅助
这些相对容易替换。另一方面,有些控件看起来像 UI,内部却相当复杂:
- 供应商制的设备控制 ActiveX
- 与打印或报表生成一体化的控件
- 内含专有文件格式读写的控件
- 承载 COM 回调或线程前提的控件
如果看错这个差异,工作量估算会一下子失控。
3.5. 浏览器依赖单独考虑
这一点相当特殊,需要单独考虑。
浏览器上的 ActiveX,与桌面端的 OCX 不同, 继续沿着现有方向发展下去的理由已经相当薄弱。
原因很简单:现代浏览器的技术基础已经不再以此为主战场。 Microsoft Edge 本体并不支持 ActiveX。 IE 模式则是针对已设置的站点使用 IE 系引擎,作为让 ActiveX 等部分 IE 功能继续运行的兼容层来使用。
也就是说:
- 现在能做到 延命
- 但作为长期设计而言,未来空间并不宽
嵌入 Windows 应用中的 WebBrowser 控件也是同样的情况。
WebBrowser 依然带着 IE 系的世界观,如果只是想显示 HTML,从现在开始的新工作更适合把 WebView2 作为第一选择。
不过这里需要注意,WebView2 并不是 WebBrowser 的完全替代件。
- 依赖 IE DOM 的脚本
- ActiveX 依赖
window.external相关的前提- 安全区域或内网前提的行为
这些都不会原样迁移过去。 如果要替换,不仅是渲染引擎,浏览器与原生代码的连接面 也需要重新设计。
4. 容易搞乱判断的论点
4.1. 是 UI 部件,还是承载规格的部件
这是最重要的一点。
老旧的表格或日历控件,只要看外观和事件是否兼容,事情大多就能推进。 而承载设备控制、报表或专有格式的 ActiveX,外观背后往往是一整块规格。
看起来同样是「界面上的一个控件」,实际差异可能有这么大:
- 只是一个列表显示部件
- 用专有协议向设备发送指令的部件
- 内部已经处理了超时、重连、重发、异常吸收的部件
- 背负着打印或导出格式兼容性的部件
对后者贸然重新实现,通常会变成一场规格发掘项目。 这类情况最好先封装。
4.2. 32bit / 64bit 与进程边界
这一点经常被忽视,但相当本质。
in-proc 的 OCX 必须与加载它的进程 bitness 一致。 也就是说,不能把 32bit OCX 原样加载进 64bit 应用。
这时现实可行的选项,大致是以下三种:
- 暂时让宿主应用也保持 32bit
- 关进独立的 32bit 进程,与 64bit 一侧通过 IPC 或 out-of-proc COM 连接
- 从能够去掉该 OCX 依赖的地方开始先行替换
「反正是 Any CPU,应该能解决吧」这种想法,通常不管用。 即使在新的 .NET 一侧构建 COM 兼容入口,managed 代码表面上的样子和实际 COM host 的 bitness 是两个不同的问题。 如果在这里草率开始,就会出现「能编译通过,但在部署环境里跑不起来」这种令人头疼的情况。
4.3. 注册、分发、权限、许可
技术上能调用,却在分发环节死掉。 这在 ActiveX / OCX 上相当常见。
容易出问题的地方包括:
regsvr32的执行方式依赖于个人经验- 依赖 DLL 的部署方式是隐性的
- 需要管理员权限,却没有落实到运维流程中
- 供应商制控件的 design-time / runtime 许可证是分开的
- 在开发机上能跑,但在干净环境中跑不起来
这些问题即使一行代码都不改,也足以让项目停下来。
有些情况下,无需注册的架构或 side-by-side 部署方式能带来帮助,但它们不是万能的。 仍然需要确认容器一侧或分发方式的兼容性。
归根结底,ActiveX / OCX 的迁移不仅是实现层面的工作,也是分发设计 的工作。 如果把这件事往后拖,往往会在最后阶段摔得很惨。
4.4. STA / 消息循环 / 回调
ActiveX / OCX 不只是单纯的 DLL 调用。 它有时会带有 COM 线程模型或消息循环的前提。
尤其需要注意的场景包括:
- 只有在 UI 线程前提下才能稳定运行
- 明明是 STA 前提,却被 MTA 一侧随意调用
- 同步调用过程中回调却返回了
- 接收事件所在的线程前提比较模糊
这类问题最初往往以「偶尔会卡住」「偶尔事件收不到」这种灵异现象的面貌出现。 但其本质大多是违反了前提条件。
因此,无论是封装还是替换, 最好提前固定好:在哪个线程创建、在哪个线程调用、在哪里接收事件。
4.5. 有没有测试、能否观测
替换之所以困难,不仅是因为代码老旧。 更重要的是没有一个标准,能用来判断「表现是否一致」。
哪怕只有以下这些东西,也会有很大帮助:
- 按操作场景划分的冒烟测试
- 输入输出样例
- 界面截图或报表样例
- 错误模式与预期行为
- 超时或设备未连接时的日志
尤其涉及设备或报表时,往往会出现「实物的行为比规格书更可信」这种奇怪的现象。 如果这里没有观测手段,替换工作就会变成一场考古发掘。
5. 各类典型场景的建议
5.1. 目前仍稳定运行的内部桌面应用
建议偏向保留。
满足以下条件的话,往往不需要勉强剥离:
- 仅限公司内部使用
- 目标终端或 OS 相对固定
- 该 OCX 只在少数几个界面中使用
- 改造需求较小,生命周期也能预估
不过,不应该原样裸放在那里, 而应该至少把调用位置收敛起来,这样后面会更省事。
也就是说,方针大致是这样:
- 目前保留
- 但先整理好边界
- 等需要替换时,能从这里直接着手
这种三段式的方式是比较自然的选择。
5.2. 想把 32bit OCX 搬到 64bit 一侧
建议是 封装 / 调整架构。
这里如果正面硬闯,会走入死路。 因为 32bit OCX 无法以 in-proc 方式加载进 64bit 进程。
现实中,比较好处理的方式是把它关进 32bit 的辅助进程或 LocalServer, 再让 64bit 应用通过粗粒度的 API 与其通信。
sequenceDiagram
participant App as 64bit .NET 应用
participant Bridge as 32bit 辅助进程 / LocalServer
participant Ocx as 32bit OCX
App->>Bridge: 用粗粒度 API 发起请求
Bridge->>Ocx: in-proc 调用
Ocx-->>Bridge: 返回结果 / 事件
Bridge-->>App: 转换后的结果
这里的要点是,不要把细粒度的方法原样全部转发。 进程间边界一旦流转大量细碎调用,很快就会变得难以维护。
- 把粒度收敛到「1 次操作 = 1 次请求」左右
- 把返回值和错误整理成有意义的单位
- 在边界处记录日志
保持这种形式,之后真正替换内部实现时也会更轻松。
5.3. IE / WebBrowser 前提的界面
建议是 优先替换。
这是「现在能跑」与「今后也能轻松维护」不太一致的领域。 IE 模式在兼容性上确实帮了很大忙,但前提依然是 IE 系的世界观。
因此,比较清晰的思路是这样区分:
- 为了不影响公司业务,先用 IE 模式延命
- 但不要把延命与长期设计混为一谈
- 替换方向可以从 WebView2、纯 Web、原生 UI + Web 混合方案中选择
尤其是如果 WebBrowser 控件只是被当作一个简单的 HTML 查看器使用,
那么替换的优先级就相当高。
而如果浏览器内的 ActiveX 还承担着本地文件、设备、签名、专有插件之类的角色, 那就不只是渲染引擎的更换,而是 原生联动的重新设计。 这部分的话题会明显更重。
5.4. 承载设备控制或专有规格的 ActiveX
建议是 先封装。
这类部件外表简单,内部却相当复杂。 即使 SDK 的资料很薄,也可能因为在现场长期运行, 暗中积累了这些行为:
- 连接失败时的等待方式
- 超时后的重试
- 事件顺序
- 用来吸收实机怪癖的规避处理
- 异常或错误代码的解读方式
这类部件如果因为「反正是老旧的」就重新实现,现场测试很大概率会炸。
因此,从下面这个顺序开始会比较安全:
- 把现有部件关进边界内部
- 补充日志,让内部发生的事情变得可见
- 收集测试场景与实机模式
- 之后再切出可以替换的范围
看起来不起眼,但在实务中,这往往是最有效的做法。
6. 常见的反模式
| 反模式 | 问题所在 | 首选修正方式 |
|---|---|---|
| 因为有 ActiveX 就全面重写 | 容易出现规格遗漏和工作量爆炸 | 先盘点资产,切出边界 |
| 试图把 32bit OCX 直接放进 64bit 应用 | 原理上不可行 | 隔离到 32bit 一侧,或调整架构 |
| 界面代码到处直接调用控件 API | 容易变得无法替换 | 收敛到 adapter / facade |
靠人工方式执行 regsvr32 步骤 |
环境差异会导致每次都出事 | 考虑安装程序、脚本、manifest 化 |
| 有 IE 模式就觉得安心 | 容易把延命和长期方案混为一谈 | 制定替换计划与结束条件 |
| 替换前没有记录行为 | 无法判定是否完成 | 准备冒烟测试、样例数据、日志 |
其中在实务中特别常见的有 3 个:
- 急于全面重写
- 轻视 bitness 的壁垒
- 把 API 散落到整个应用中
只要避开这 3 点,事故率就会明显下降。
7. 开始迁移时的检查清单
ActiveX / OCX 的项目,与直接动手实现相比,先做资产盘点会更顺利。顺序大致如下:
- 梳理使用中的 OCX / DLL
- 文件名、版本、ProgID、CLSID、供应商、是否有许可证
- 梳理在哪里使用
- 界面、功能、报表、设备、批处理、Office 联动等
- 确认 bitness 与宿主条件
- 32bit / 64bit、in-proc / out-of-proc、STA 前提、浏览器依赖
- 确认分发条件
- 注册方式、依赖 DLL、管理员权限、静默安装、干净环境下能否复现
- 制作冒烟测试
- 不只是正常路径,也包括失败、未连接、超时的情况
- 建立边界
- adapter、service、facade、跨进程桥接等
- 以 1 个界面、1 个功能、1 台设备等小单位先行验证
- 从验证成功的边界开始,逐步扩大 保留 / 封装 / 替换 的范围
如果跳过这些步骤,之后甚至很难说清楚「当时到底难在哪里」。
8. 大致的使用区分
| 情况 | 首选方案 |
|---|---|
| 仅限公司内部使用、稳定运行、改动很小 | 保留 |
| 只想让周边 .NET 化 | 封装 |
| 32bit / 64bit 相冲突 | 封装 / 调整架构 |
| IE / WebBrowser / 浏览器 ActiveX 依赖 | 替换 |
| 单纯的 UI 部件且有替代方案 | 替换 |
| 承载设备控制、报表、专有规格 | 封装 |
| 注册或分发每次都出问题 | 封装或替换 |
拿不准的时候,先分辨清楚 这是 UI 部件,还是承载规格的边界面,判断就不容易出错。
9. 这类相谈很适合我们
这个主题,哪怕只是在正式开发之前做 方针整理,也很有价值。
例如,以下这些咨询相当合适:
- 想盘点一下到底该替换哪些 OCX
- 只想先整理清楚 32bit / 64bit 的卡点
- 想迁向 .NET,但希望保留 COM 入口
- 想比较供应商已停止维护的 ActiveX 的延命方案与撤退方案
- 想看看能从哪里开始剥离 IE / WebBrowser 依赖
- 想先安全地分离出 1 个界面、1 个功能
ActiveX / OCX 的项目,胜负往往取决于 如何切分边界,而不是实现本身。 在全面改造之前,先从现状梳理、架构比较、迁移顺序设计入手,往往就已经很有意义。
10. 总结
如何处理 ActiveX / OCX,不是靠「因为是遗留资产就讨厌它」来决定的事情。
首先要看的要点有 4 个:
- 这个部件只是单纯的 UI,还是承载规格的边界面
- 是否必须在同一个进程中使用
- 32bit / 64bit、注册、浏览器依赖、许可证会不会卡住
- 替换之前,能否观测到它的行为
只要看清这 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 フォーム ActiveX コントロール インポーター)
- 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: 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: COM 的 STA/MTA 基础 - 线程模型与避免 Hang 的思路
- KomuraSoft Blog: 从 C# 调用 C++ 原生 DLL 时,为什么最好用 C++/CLI 制作封装层
- KomuraSoft Blog: COM 有用的案例研究 - 从 32bit 应用调用 64bit DLL 时
相关文章
共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。
委托开发 Windows 应用程序前该梳理的事项
在委托外包开发 Windows 应用程序之前,梳理现有软件改造、设备联动、COM/ActiveX、发布与更新、维护等需要注意的要点。
COM/OCX/ActiveX 开发中容易踩坑的注册与位数陷阱
本文从实务角度整理 COM、OCX、ActiveX 开发中容易踩坑的 32bit/64bit、Visual Studio 2022、regsvr32/Regasm、管理员权限、HKCR、STA/MTA 等问题。
COM / ActiveX / OCX 是什么 - 区别与关系整理
从实务角度厘清 COM、ActiveX、OCX 三者的区别与关系:COM 是 Windows 组件互操作的二进制契约底层,ActiveX 是以 COM 为基础的可嵌入控件语境,OCX 则是 ActiveX 控件常见的扩展名。读完就能分清机制、组件、文件这三层边界。
什么是 COM - 为什么 Windows COM 的设计至今依然优美
本文从 Windows COM 的接口设计、IUnknown、GUID、二进制兼容性等角度整理 COM 是什么,并说明它至今依然适用的原因。
不只是 appsettings.json ── Windows 业务应用的配置管理实务(环境差异化设置・敏感信息・写入位置)
本文从实务角度整理 Windows 业务应用的配置管理,涵盖 appsettings.json 的分层、IConfiguration 与 IOptions/IOptionsSnapshot/IOptionsMonitor 的选用方式、环境差异化设置、可写入配置的存放位置、敏...
常见问题
汇总了咨询这一主题时常见的问题。
- ActiveX / OCX 应该替换吗?
- 不应该单纯看「是否老旧」,而要看这个部件承担了什么职责来判断。如果只是有替代品的普通 UI 部件,就替换;如果承载着设备控制、报表或专有文件格式,就先封装,理清边界;如果一直稳定运行且改动范围很小,保留也是现实的选择。「干脆全面重写」和「因为害怕就永久冻结」这两种做法出问题的概率都很高。
- 32bit 的 OCX 能从 64bit 应用中使用吗?
- 以 in-proc 方式是不能的。OCX 必须与加载它的进程 bitness 一致,这是原理上的限制。现实可行的选项有三个:暂时让宿主应用也保持 32bit;把它关进一个独立的 32bit 进程(辅助 EXE 或 COM LocalServer),再通过 IPC 或 out-of-proc COM 与 64bit 一侧连接;或者从能够去掉该 OCX 依赖的地方开始先行替换。
- 浏览器中的 ActiveX 依赖该怎么处理?
- 更适合以替换为优先。Microsoft Edge 本体并不支持 ActiveX,IE 模式的定位只是一种延命措施。WebBrowser 控件同样带着 IE 系的世界观,如果只是想显示 HTML,WebView2 是第一选择。不过 WebView2 并不是完全对等的替换件,依赖 IE DOM 的脚本以及 window.external 相关的前提,都不会原样迁移过去。
- 「封装」ActiveX / OCX 具体是指做什么?
- 是指把 ActiveX / OCX 关进一个狭窄的边界内部,对外则以新的 API 或新的界面部件呈现。常见的形式有 WinForms 宿主 + AxHost、通过 32bit 辅助 EXE 或 LocalServer 做跨进程桥接,以及在 .NET 一侧提供 COM 兼容入口。封装时不要把旧 API 原样大量复制,而应该做成粗粒度的方法,在边界上明确日志、超时和异常转换的职责,并让未来的替代实现也能用同一个接口无缝换入。
作者简介
本文作者的个人简介页面。
Go Komura
小村软件有限公司 代表
以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。