news 2026/10/5 6:06:00

AVEVA Marine C#二次开发入门:从零创建第一个自定义命令

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AVEVA Marine C#二次开发入门:从零创建第一个自定义命令

做船舶与海工设计软件这一行,我已经和 AVEVA Marine 打了超过十年交道。老同事叫它 Tribon,新文档里叫 AM,名字换来换去,核心没变:它是目前国内船厂和设计院里覆盖率相当高的三维船舶设计平台。最近两三年,问“AVEVA Marine C# 二次开发怎么入门”的人越来越多,问法五花八门:“第一个程序怎么跑起来”“能不能批量创建支架”“C# 到底能不能写 AM 插件”等等。老实说,AM 的官方 SDK 把入口都给好了,但资料分散、版本差异大,新手很容易卡在第一步。这个系列我就从入门讲起,目标只有一个:让你亲手把一个用 C# 写的自定义命令跑进 AM 环境里。这篇是 001,先从环境、框架和最小 demo 讲透。

1. 为什么 AVEVA Marine 的二次开发绕不开 C#

1.1 大型船舶设计软件里的“定制刚需”

AM 这类软件有个特点,模型里塞满了板、型材、管系、设备、电缆托架这类对象,数据库关系复杂,单个功能做得很深,但不可能照顾到每家船厂的“特殊习惯”。举个例子,有的船厂要求出图时把零件名按特定规则重排,有的要求批量生成某一区域的加强筋,有的希望模型里某个属性一变,BOM 就自动更新。这些需求用原生功能去拼,要么根本没有这个按钮,要么点完之后还要手工调整几十次。

我刚入行那年,遇到过最典型的需求:一整条船的电缆托架统计,靠人肉从图纸里数,三个设计员数了两天,还有错漏。后来我用 AM 的 COM 接口写了个小工具,十几分钟跑完全船数据。从那时候我就明白一件事:AM 的项目规模越大,流程越特殊,二次开发就越不是锦上添花,而是刚需。只要你还在这行做设计管理、模型深化或者出图流水线,你早晚会碰到“官方功能做不到,手工做想哭”的场景,这时候自定义命令就是最优解。

1.2 C# 在工业软件生态里的位置

如果你平时关注各种 CAD/CAE 软件的二次开发,会发现 C# 在工业软件里几乎是通用语言。Revit 二次开发能写 C#,UG NX 的 NXOpen 用 C# 用得很多,VisionPro 这类机器视觉软件支持 C#,AVEVA 自家的 Smart 系列也以 .NET API 为主。为什么大家不约而同选 C#?理由其实很朴素:AM 本身就是跑在 Windows 上的 .NET 应用,用 C# 开发等于和它“同文同种”,调用 API 的体验最顺畅。

对比另外两条路线会更清楚。C++ 性能确实强,但开发成本高,光是把一个自定义界面接入 AM 的窗口体系,就够新手折腾一个月。Python 虽然轻量,但 AM 对 Python 的官方支持远不如对 .NET 来得完整,很多底层对象你用 Python 调就是绕不过去。C# 夹在中间,刚刚好:写界面有 WPF/WinForms,访问数据库有 ADO.NET,调第三方库有 NuGet,再加上 Visual Studio 的调试体验,做工程项目工具非常合适。所以我的建议很直接,新项目直接走 C#,别想着先用脚本试试水,回头迟早要重写。

1.3 二次开发不是“外挂”,是官方支持的正规扩展

在技术群里经常有人问“C# 可以给 AM 写外挂吗”,每次看到我都得纠正一下。AM 官方提供了 SDK,里面有完整的接口定义、示例代码和技术文档,你写出的插件是跑在官方认可的工作流里的。它属于软件扩展,不是绕过授权、篡改程序行为的外挂。搞清楚这一点很重要,它决定了你后续学习的路径:你是去读官方文档、照 SDK 示例做,而不是去网上找破解思路、逆向内存数据。

心态摆正之后,学起来反而简单。AM 的 API 再庞大,入门也无非是“找到入口、调用接口、处理结果”这三板斧。你不需要把所有类都背下来,只需要知道怎么找、怎么用、怎么调试,剩下的事情都是堆量和积累。

2. 入门前先弄明白 AM 二次开发的整体框架

2.1 站点、工程、模型库三者的关系

很多新手一上来就急着写代码,结果连“站点”是什么都没搞懂,代码写完也不知道往哪儿放。这里我用大白话拆一下 AM 的组成。你可以把 AM 理解成一个“设计操作系统”,它不是一个孤立的单机软件,而是由服务器、工作站、数据库共同组成的系统。

“站点”(Site)是 AM 环境里的核心配置集合,里面记录了数据库连接、模块列表、权限设置、菜单和命令注册信息。你的 C# 插件能不能被 AM 发现,主要就看站点配置里有没有登记。“工程”(Project)或“模型库”(Schema)则是具体的数据存储空间,船体模型、管系模型、设备模型都存在里面。二次开发的大部分操作,本质上是“通过站点提供的入口,去读写工程模型里的对象”。

这个关系搞不明白,后面会遇到一个很经典的问题:插件明明已经编译成功了,但 AM 里就是找不到命令。大概率就是你把 DLL 放错了地方,或者站点配置文件没有更新。记住一句话:程序集文件只是“货物”,站点配置才是“入库单”,两样东西缺一不可。

2.2 官方提供的四种开发方式,先做哪一种

AM 的 SDK 提供了多种扩展方式,从入门到进阶大概可以分成四类。

第一类是自定义命令(Command),这是最基础的入口。你在 AM 里输入一个命令名,或者点一个按钮,系统就调用你写好的方法。入门第一个 demo 做这个就行,链路短,问题容易排查。

第二类是自定义界面(UI 扩展),比如在 AM 的侧边栏加一个 WPF 面板,把按钮、输入框、数据表格集成进去。这种适合做“工具箱”类型的工具,但涉及界面与 AM 主进程的交互,复杂度比命令高不少。

第三类是事件订阅。AM 在执行某些动作时会抛出事件,比如模型对象被修改、被创建、被删除。你可以监听这些事件,在后台自动做校验、计算或者数据同步。这类功能很强大,但事件机制在不同版本的 API 里差异比较大,建议有基础之后再碰。

第四类是批处理和后台任务。不打开交互界面,通过命令行或计划任务批量处理模型数据,适合文档生成、数据抽取、批量属性修改这些跑批场景。

对 001 篇来说,只盯第一类自定义命令就够了。把命令这条路跑通,你能理解 AM 插件从编译到加载的完整过程,后面学 UI、事件、批处理会轻松很多。

2.3 开发环境搭建与版本注意事项

开发环境本身不复杂,但版本问题最容易坑人。我建议按这个组合来准备:AM 本体装好后,找到安装目录下的 SDK 文件夹,里面通常有 DLL、示例代码和 PDF 文档,这是第一手资料。Visual Studio 建议用 2019 或 2022,项目类型选“类库”,目标框架选 .NET Framework 4.7.2 或 4.8,具体以你本地 AM 支持的版本为准。AM 进程本身是 64 位,所以项目的“平台目标”一定要设置成 x64,否则后面会报 BadImageFormatException。

还有一点必须提醒:AM 的不同版本之间 API 命名和接口签名可能有差异。你在这个版本的 SDK 里找到的接口,换一个版本未必还叫这个名字。所以我在文章里给的代码只作为思路参考,真正的“标准答案”一定在你本地 SDK 的示例代码里。装完 AM 之后,先花半小时找到 SDK 自带的 Command 示例,照着它跑一遍,比看十篇教程都管用。

3. 第一个 C# 程序:从新建工程到命令跑起来

3.1 新建类库项目,引用 SDK 程序集

打开 Visual Studio,新建一个 C# 类库项目,项目名称建议起得像样一点,比如 MyFirstAmPlugin,别用默认的 ClassLibrary1。建好之后,先别着急写代码,把引用配好。在“解决方案资源管理器”里右键“添加引用”,浏览到 AM 的安装目录,找到 SDK 下的核心程序集。

不同版本的 DLL 名字会有差异,但通常在 SDK 文件夹里能看到类似AVEVA.Marine.Api.dll、AVEVA.Marine.UI.dll、AVEVA.Marine.Model.dll这样的文件。引用的时候要看仔细,尽量引用你打算用到的模块。如果找不到这些 DLL,还有一个笨办法:在 AM 安装目录下全文搜索“*.dll”,然后看文件名里带 AVEVA 的,基本就是核心程序集。添加完引用之后,在引用项的属性里把“复制本地”改成 false,因为运行时 AM 自己会加载这些程序集,不需要拷贝到输出目录。

这一步经常有人犯错:明明添加了引用,编译也过了,一运行就报“找不到类型”。原因八成是你引用的 DLL 版本和当前 AM 版本不一致,把版本混用了。我的经验是,每台机器上只保留一个 AM 版本对应的 SDK 引用路径,不要把多个版本的 DLL 混在同一个项目里。

3.2 一个最小命令的代码长什么样

下面是一份剥离了业务逻辑的最小示例,目标只有一个:在 AM 环境里弹出一个消息框,证明你的代码已经被加载并且执行了。命名空间和接口名按不同版本会略有差异,我在这里写的是通用骨架,你看完理解思路,具体名字以本地 SDK 的模板为准。

using System.Windows.Forms; // 不同版本命名空间会有差异,请以 SDK 文档为准 using AVEVA.Marine.Api; namespace MyFirstAmPlugin { [CustomCommand("HULL.HelloFromCSharp")] public class HelloFromCSharp : ICustomCommand { public void Execute(CommandContext context) { MessageBox.Show("Hello AVEVA Marine, from C#!"); } } }

这段代码里的CustomCommand特性用来声明命令名,HULL.HelloFromCSharp是你在 AM 里输入的命令关键字,可以按模块缩写来命名,比如HULL.开头就表示船体模块的命令。ICustomCommand接口要求你实现Execute方法,方法里的context参数携带了当前 AM 环境的上下文,包括当前选中的对象、活动工程等信息。入门阶段,你只用它来弹个窗口,证明链路通了就行。

如果你在 SDK 示例里看到的类名不叫ICustomCommand,或者特性名不一样,千万别硬套。这时候你应该打开本地 SDK 的 Command 示例,把它的模板拷过来,替换成自己的逻辑。接口叫什么不重要,重要的是你把“命令生命周期”这套机制跑通。

3.3 编译、签名、注册三步走

代码写完,编译之前还差一个关键动作:给程序集签名。AM 加载插件时会做程序集签名校验,没有强名称签名,很多版本根本不会加载你的 DLL。操作方法是:在项目属性里找到“签名”页签,勾选“为程序集签名”,然后新建一个强名称密钥文件。文件类型一般是.pfx或.snk,自己学习用可以顺手建一个放在项目目录里;如果公司有统一的签名密钥,用公司的,别自己另造一套。

签名完成之后,编译项目,你会得到一个MyFirstAmPlugin.dll。接下来就是注册环节。先把 DLL 拷贝到 AM 对应的程序目录,通常是 AM 安装路径下的 Bin 目录,具体位置看你们公司的部署方式。然后打开站点配置文件夹,找到命令定义文件,在里面加一条命令记录,把命令名指向你刚写的类和 DLL。这一步不同版本差异很大,有的版本提供图形化的命令注册工具,有的版本需要手改 XML。

最稳妥的做法是直接参照 SDK 示例里的注册说明。你不需要背下路径,只需要理解原理:AM 启动时读取站点配置,配置里说“有这么个命令,由这个 DLL 里的这个类处理”,于是当你输入命令名时,AM 就找到你的程序集来执行。把这个链路记住,后面换版本、换环境,你都能自己倒腾明白。

3.4 调试技巧:附加进程比反复重启好用

第一个 demo 能跑通之后,接下来你一定会遇到“程序没反应”的情况。最业余的调试方式是改一下代码,重新编译,重启 AM,再点一次。这样不是不行,但效率太低,一次循环可能要两三分钟。我的习惯是直接用 Visual Studio 的“附加到进程”功能。

先把 AM 启动起来,然后在 VS 里选择“调试 -> 附加到进程”,在进程列表里找到 AM 的主进程(名字通常和 AM 主程序保持一致),附加进去。后面你代码里的断点就能命中了。如果是整个项目从零开始的调试,也可以直接把 VS 的“启动外部程序”设置成 AM 的 exe,按 F5 之后 VS 自动启动 AM 并附加调试器,效率更高。

还有一个非常土但很有效的方法:在Execute方法第一行就弹一个MessageBox,用来确认“代码已经进来了”。如果没弹,说明没加载到你的程序集;如果弹了,说明链路是通的,后续再往下调。这种暴力验证法在早期非常管用,能帮你快速区分问题出在“加载阶段”还是“业务逻辑阶段”。

4. 实操中容易被坑到的五个细节

4.1 平台目标不改成 x64,命令一执行就崩

这个问题我见过太多次了。默认新建的类库项目,平台目标往往是“Any CPU”,这在普通桌面程序里没问题,但 AM 的主进程是 64 位的。如果你的插件以 x86 模式编译,加载进 64 位进程时,CLR 会因为体系结构不匹配直接抛BadImageFormatException,命令根本没机会执行。

解决方法非常简单:项目属性 -> 生成 -> 平台目标 -> 选 x64。改完之后重新编译,再跑一次。我在带新人的时候,这个坑几乎每个人都会踩一遍,所以我把它放在踩坑清单的第一条。还有一个相关的小坑:如果你在同一个解决方案里同时引用了 x86 和 x64 的原生 DLL,也可能触发类似错误,这时候要检查所有引用的程序集,确保目标平台一致。

4.2 没有强名称签名,加载阶段就被拒

前面说了签名的重要性,这里再展开讲为什么。AM 基于 .NET Framework 运行,对插件的程序集完整性和来源有校验机制。没有强名称签名,或者签名的公钥和站点配置里记录的不一致,加载时会被拒绝,表现就是命令找不到、插件被静默忽略。

解决办法是统一的。个人学习用自己生成的密钥文件,公司项目用团队统一的密钥文件。注意密钥文件不要随便改动,一旦换了密钥,之前发布出去的插件全部失效。另外一个容易忽略的点是:签名之后,程序集的版本号也会参与加载判断。如果今天编译出的 DLL 版本是 1.0.0.0,明天改成 1.0.1.0,站点里记录的版本没同步更新,照样可能加载失败。

4.3 改了代码没生效,多半是拷贝错了目录

新手还容易犯一个低级错误:代码改了,重新编译了,但 AM 加载的还是旧 DLL。原因通常是把 DLL 同时放到了多个目录,AM 加载了其中一个旧副本,你却在另一个目录里更新文件。排查方法也很简单,在代码里写一个文件日志,启动时把当前程序集的路径和版本号记录下来,一看就知道加载的是哪个文件。

这个问题的本质,是“工程输出目录”和“AM 插件目录”没有建立清晰的对应关系。我的做法是把“复制到输出目录”和“发布脚本”固定下来,每次编译后自动把 DLL 拷贝到指定目录,省得手工操作出错。等你项目多了,这一步自动化能帮你省掉大量“改了没反应”的排查时间。

4.4 接口版本与 AM 版本不匹配,报一堆莫名其妙错误

AM 的 API 不是一成不变的。从老版 Tribon 演化到 AM 202x,接口经历了好几轮调整。你拿着 2023 版本的 SDK 示例代码,放到 2019 版本的环境上编译,很可能连命名空间都找不到。反过来,在旧版本上写的插件,到了新版本环境里,也可能会因为接口废弃而运行异常。

所以我在前面的章节特别强调:以本地 SDK 为准。如果你要在多个版本的 AM 上维护同一个工具,最好用条件编译或抽象层把版本差异隔离起来,避免一个版本升级就把所有插件带崩。入门的读者不用管这么深,但心里要有这根弦:哪天你在网上找到一个看着很牛的示例代码,先看一眼对方用的 AM 版本,再决定要不要照抄。

4.5 权限不足,站点配置改不动

AM 在正式环境里通常由 IT 统一部署,普通账号可能没有站点配置文件夹的写权限。这时候你辛辛苦苦改好了命令定义,保存的时候提示权限不足,又得找管理员重新发权限。我建议第一步先去确认当前账号对 AM 安装目录和站点目录有没有完全控制权限,没有就先找管理员开权限,别等代码写完再卡在这个环节。

5. 常见问题排查速查表

我把平时被问得比较多的问题整理成一张速查表,方便你卡住的时候快速定位。表格里写的不是标准答案,是实战环境里最常见的排查方向。

现象可能原因排查与解决思路
输入命令名提示 Command Not Found站点配置没登记命令,或者命令名拼写不一致检查命令定义文件,确认CustomCommand特性里的名称与输入一致
命令执行后直接报 BadImageFormatException项目平台目标不是 x64项目属性中将平台目标改为 x64,重新编译
命令没有反应,也没有报错异常被捕获后吞掉,或者 DLL 没有被加载附加 VS 调试器,或者先弹 MessageBox 验证入口
程序集加载失败,提示强名称问题DLL 缺失签名,或签名密钥不一致在项目签名页启用强名称签名,统一密钥文件
插件在 A 机器上正常,B 机器上不工作AM 版本或站点配置不同检查两台机器的 AM 版本、SDK 引用版本和站点配置差异
修改模型对象时提示只读或不可写没有进入事务/修改模式,或权限不足查看 SDK 中关于事务和文档修改模式的说明,确认操作权限

这张表只是开始,后面随着系列推进,我会把建模、UI、数据抽取这几个方向各自的坑也整理出来。现在你先把它当做一个排查入口,遇到问题先对照现象,再决定从哪个方向深挖。

6. 从第一个命令到一个能用的工具,接下来做这三件事

第一个命令跑通之后,你已经跨过了入门最难的心理障碍。接下来想做一个真正能用的工具,我个人建议按这个顺序推进。

第一件事,学会读模型属性。AM 的模型对象有大量属性,比如板的厚度、材质、型材的规格、管系的直径。先写一个命令,选中某个模型对象,把你的属性读出来,用 MessageBox 或者写入日志显示出来。这一步能帮你理解模型对象的结构,也为后面做数据抽取打基础。

第二件事,学会改属性。读出来之后,试着改一个属性值,比如把某个板厚从 10 改成 12。注意改属性的时候通常需要进入修改模式或事务,否则会提示只读。这个环节能让你掌握“写操作”的基本套路,是批量修改工具的核心。

第三件事,做一个最简单的批量操作。比如遍历某个区域的所有加强筋,统计数量并导出到文本文件。不需要做得很复杂,重点是掌握遍历模型对象的 API,以及异常处理。

我个人的体会是,AM 的 C# 二次开发入门并不难,真正难的是愿不愿意把一条命令做到极致。很多人上来就想做一个全流程自动建模的大系统,结果卡在第一个实体创建上,然后就开始怀疑自己。我更建议你从一个小到不能再小的工具开始,把命令、调试、日志、异常处理这套流程跑顺,后面的事情其实就是堆量和积累。每做一个新工具,就把一个官方示例吃透,一年下来,你手里的插件库会越来越厚实,那时候你就不会再问“怎么入门”,而是会想“下一个工具该做什么”了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 6:05:41

CentOS7下Cadence INCISIVE152安装全攻略:从依赖库到License配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:04:11

多传感器融合时间同步:STM32实现Livox雷达PPS硬件同步实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:02:42

MATLAB接入本地DeepSeek:用Ollama打造私有化AI编程助手

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:02:07

STM8实战:UART1、EEPROM、FLASH与IIC外设开发避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:01:51

MRAM替代SPI Flash实战:MR25H40CDF与STM32L031K6工业存储方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华