当前位置: 首页 > web >正文

# 检测 COM 服务器在线状态

适用场景

  • OPC DA/OPC AE 等基于 DCOM 的工业软件巡检
  • 自动化部署脚本中批量验证远程 COM 组件是否可用
  • Windows 服务开机自检

1. 背景

在工业控制与运维场景下,我们经常需要判断某台机器上的 COM / DCOM 服务器(例如 OPC Server)是否存活,并在掉线时及时告警或自动重连。
.NET 自带的 System.Type.GetTypeFromProgID / Activator.CreateInstance 能直接拉起组件并建立 Secure Channel;结合异常捕获即可快速判定服务可达性。


2. 核心代码

/// <summary>
/// 判断 COM 服务是否在线
/// </summary>
/// <param name="progId">ProgID,例如 “Kepware.KEPServerEX.V6”</param>
/// <param name="remoteHost">远程主机;可为 “localhost”/计算机名/IP,默认本机</param>
/// <returns>true = 在线;false = 离线/异常</returns>
public bool TestComOnline(string progId, string remoteHost = "localhost")
{try{// ① 获取 COM 类型(若未注册或无权访问将返回 null)var type = Type.GetTypeFromProgID(progId, remoteHost, true);if (type == null) return false;// ② 激活对象。默认 CLSCTX_INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER (0x15)var obj = Activator.CreateInstance(type, null);// ③ 立即释放,避免资源泄漏Marshal.ReleaseComObject(obj);return true;}catch (COMException ex) when (ex.HResult == unchecked((int)0x800706BA) ||  // RPC_S_SERVER_UNAVAILABLEex.HResult == unchecked((int)0x800706BE))    // RPC_S_CALL_FAILED{_logger.LogError($"TestComOnline COMException: {ex.Message}");return false;   // 通道建立失败 → 服务端不在线 / 防火墙阻断}catch (Exception ex){_logger.LogError($"TestComOnline Exception: {ex.Message}");return false;   // ProgID 不存在、权限不足等}
}

3. 关键实现要点

步骤细节容易踩的坑
GetTypeFromProgID通过注册表 HKCR\<ProgID>\CLSID 定位 CLSID,再解析 DCOM Endpoint- 如果传入 remoteHost,要求目标机器打开 DCOM 并允许远程激活
- 若组件未注册,将抛 TypeLoadException
Activator.CreateInstance触发 DCOM 激活;若远端进程未启动,会自动拉起- 第一次拉起耗时较长,可考虑异步
- 若用户权限不足会抛 UnauthorizedAccessException
异常过滤0x800706BA/BE → RPC 通道不可达- 其它 COMException 仍可能是“离线”表现,视业务决定是否全捕获
资源释放Marshal.ReleaseComObject 及时释放 RCW- 不释放会导致 OPC Server 中对象计数增加,严重时“卡死”

4. HRESULT 错误码对照

错误码十进制说明
0x800706BA-2147023174RPC_S_SERVER_UNAVAILABLE:远程服务器不可用
0x800706BE-2147023166RPC_S_CALL_FAILED:RPC 调用失败(会话被强制关闭)
0x800401F3-2147221005CO_E_CLASSSTRING:ProgID/CLSID 格式错误或不存在
0x80070005-2147024891E_ACCESSDENIED:DCOM 未授权、UAC 拦截

5. 日志与监控建议

  • 日志级别

    • Info:周期性巡检的成功日志可降级为 Debug,避免刷屏
    • Error:捕获到 COMException 时记录 HResultremoteHost
  • 指标

    • 成功率(Success / Total)
    • 平均连接耗时(Stopwatch 统计)
  • 告警

    • 连续 N 次失败后触发短信 / Email
    • 可结合 Prometheus + Grafana 进行可视化

6. DCOM 配置检查清单

位置关键项建议
dcomcnfg组件服务目标 ProgID 所在的 应用程序 ID“安全性”里勾选 允许远程激活
Windows 防火墙RPC Endpoint Mapper (135/TCP) + 组件动态端口工控网段可考虑放行或固定端口
用户权限运行账户需在目标机 Distributed COM Users生产环境建议使用专用域服务账号

7. 完整调用示例

var servers = new[]
{("Kepware.KEPServerEX.V6", "10.1.17.5"),("Matrikon.OPC.Simulation.1", "localhost")
};foreach (var (progId, host) in servers)
{bool online = TestComOnline(progId, host);Console.WriteLine($"{host} / {progId}{(online ? "在线" : "离线")}");
}

输出示例:

10.1.17.5 / Kepware.KEPServerEX.V6 → 在线
localhost / Matrikon.OPC.Simulation.1 → 离线

8. 小结

  • TestComOnline 通过 DCOM 激活一次对象即可判断服务是否在线,轻量、准确。
  • 合理捕获典型 HRESULT,便于区分“服务器掉线”与“配置/权限”问题。
  • 在批量巡检、容器化部署或 CI/CD 流水线里,都可以快速集成这段代码。
http://www.xdnf.cn/news/15515.html

相关文章:

  • python 双下划线开头函数
  • 网络协议和基础通信原理
  • Go泛型完全指南:从基础到实战应用
  • Fluent许可文件安装和配置
  • 车载诊断框架 --- 车载诊断GuideLine
  • 如何集成光栅传感器到FPGA+ARM系统中?
  • 如何更改Blender插件安装位置呢?
  • qt 使用memcpy进行内存拷贝时注意的问题
  • 硬盘爆满不够用?这个免费神器帮你找回50GB硬盘空间
  • EasyExcel实现Excel文件导入导出
  • [Nagios Core] 事件调度 | 检查执行 | 插件与进程
  • 解决Qt中“known incorrect sRGB profile“警告的Photoshop修改方法
  • 如何基于FFMPEG 实现视频推拉流
  • DataWhale AI夏令营 Task2笔记
  • asyncio.Task` 的工作机制与高级应用
  • 嵌入式硬件篇---单稳态多谐施密特电路
  • 【WRFDA实操第一期】服务器中安装 WRFPLUS 和 WRFDA
  • 2025年睿抗机器人开发者大赛CAIP-编程技能赛本科组(省赛)解题报告 | 珂学家
  • Python `WeakValueDictionary` 用法详解
  • Kotlin委托
  • python的小学课外综合管理系统
  • MFC UI大小改变与自适应
  • ICMP隧道工具完全指南:原理、实战与防御策略
  • SwiftUI 全面介绍与使用指南
  • 【Docker基础】Dockerfile指令速览:健康检查与启动指令详解
  • Spark SQL 之 UT
  • Linux操作系统从入门到实战(七)详细讲解编辑器Vim
  • C++-多态
  • 现场设备无法向视频汇聚EasyCVR视频融合平台推流的原因排查与解决过程
  • Java Integer包装类缓存机制详解