做了这么多年船舶与海工行业的CAD/CAE平台开发,“Aveva Marine”这个名字对搞设计的人来说不陌生,对搞开发的兄弟来说就更有故事了。这是一款在船舶设计领域占有重要地位的三维设计软件,常用在船体结构、管路、电气、舾装的设计建模与出图环节。但软件再强,也不可能覆盖所有船厂的个性化流程,于是用C#做Aveva Marine二次开发就成了提升设计效率的一条实用路径。这篇内容就是这个系列的入门第一篇,目标是让没接触过AM二次开发的人也能搭好环境、写出第一个能真正访问模型数据的C#程序,搞清楚AM的API体系大致是怎么运转的。
我最早接触这类开发的时候也绕了不少弯路。网上资料零零散散,官方文档又是英文为主,版本差异还很大。遇到过引用dll报错、附加不到进程、改了属性不生效这类问题,折腾一通才发现很多坑是可以提前避开的。所以这篇我尽量把入门阶段最重要的东西讲清楚:环境怎么搭、API怎么找、核心对象怎么理解、第一个实用功能怎么写。
1. 项目概述:为什么要做Aveva Marine的C#二次开发
1.1 每天重复的建模操作,就是最值得做的事
先说一个真实场景。船厂设计人员拿到一个新的分段模型,管路专业的人要检查所有管道的口径、压力等级、材质是否符合项目标准。传统做法是什么?在AM里面一条一条管子点开属性窗口看,看完一条记一条,遇到几百条管路的时候,光查属性就能耗掉半天。而且这种纯人工检查还容易漏项,漏掉一条没有按标准建模的管道,现场返工成本就高了。
这类工作如果交给C#写的小工具来做,逻辑其实很简单:遍历当前区域的管路构件,读取管径、等级、材质等属性,拿项目标准配置做比对,不符合条件的自动标记并汇总成清单。整个过程从半天缩短到一两分钟,而且不会漏。
C#做Aveva Marine二次开发的本质,就是通过软件提供的.NET API接口,让外部程序能够连接到正在运行的AM客户端,或者以独立进程方式访问AM的设计数据库,从而实现模型数据的读取、修改、批量生成和自动化出图。它的应用范围大致能分成三类:
- 数据批量处理类工具:批量修改构件属性、批量提取设备清单、批量更新编码规则。
- 设计辅助类插件:放置标准件时自动匹配规格,绘制管道时自动检测碰撞。
- 出图自动化类功能:自动生成螺栓清单、管段图、材料报表,并定制AM的菜单和工具栏来安放这些功能入口。
1.2 入门开发最需要准备什么
先说装备。Aveva Marine的二次开发和别的工业软件二次开发(比如Creo、NX、Catia那类)不一样,它没有一个独立安装的SDK包,API就嵌在客户端安装目录里。所以入门第一件事,是确保开发机上已经装好了一个能正常运行的Aveva Marine客户端。
接着是Visual Studio。这个很关键,要看AM的版本。很多船厂用的还是多年以前的老版本,配套的是.NET Framework 3.5或者4.x,那就别一门心思装最新版VS2022,老老实实装VS2015或者VS2019更省心。版本对应关系可以大致参考下面这个表:
| AM版本方向 | 推荐Visual Studio | .NET Framework目标 |
|---|---|---|
| 较老版本(Tribon时代/AM早期) | VS2010 / VS2015 | 3.5 / 4.5 |
| 中期版本(AM400系列左右) | VS2017 / VS2019 | 4.6 / 4.7 |
| 较新版本(E3D / E3D Design方向) | VS2019 / VS2022 | 4.7.2及以上 |
这一步我建议多花点时间问一下软件管理员,确认本机的AM具体是什么版本,再决定VS版本。不要凭感觉来,我有段时间图省事直接用VS2022开发,结果引用的程序集不支持,折腾半天编译不过去,最后换了开发环境才消停。
2. 核心API体系与C#交互思路
2.1 AM的架构是一个数据库加三维显示引擎
Aveva Marine的数据管理方式和普通三维软件不太一样。它的模型不是一堆文件,而是存在一个中央数据库里。你在AM里面看到的每一个船体结构件、每一根管子、每一个设备,在数据库里都是带有属性值的元素(Element),元素之间体现为父子层级关系。这种设计的好处是多专业、多用户能同时在一个项目里协同工作,同时也给二次开发留下了很好的数据访问路径。
先打一个比方:AM的主程序像是一个餐厅前台,API就是你到后厨拿菜的窗口。你要取哪道菜、改哪道菜的口味,得通过明确的点单方式传给后厨,不能自己冲进厨房乱翻。在AM里,这个“点单方式”就是API提供的各种入口:通过当前选择的元素获取对象、通过项目数据库查找元素、通过类型和属性过滤出符合条件的构件集合。
C#程序访问AM数据核心是三个东西:
- 数据库连接对象:负责建立会话,连接当前打开的项目数据库。
- 元素(Element)对象:代表数据库里的模型或数据记录。
- 属性(Attribute)对象:元素上的具体字段,比如管径、壁厚、保温等级。
理解了这三层,大部分入门需求就能覆盖。比如你要批量修改某条管路的标签,本质就是定位到管路元素,修改它的某个属性字段,然后提交保存。
2.2 两种开发模式的对比:进程内插件和独立外部工具
AM的第二种开发方式,是写一个完全不依赖AM界面、独立运行的外部批处理工具。这种程序通过API直接连接数据库,适合做晚上定时跑的批量任务。它不占用AM客户端的用户界面,适合处理大批量数据操作,但无法实时获得用户在界面上的操作反馈,而且要自己处理数据库连接和释放的问题,出错排查也麻烦一些。
我个人的建议是,入门阶段优先做进程内插件。它的调试链路短,逻辑直观,能直接在AM界面里看到效果,对建立信心很重要。等把数据访问、属性读写这套逻辑跑通了,再去做独立工具会顺手很多。
2.3 如果从其他CAD软件的二次开发转过来,有几个认知要调整
首页热搜里面出现了Creo、NX、Catia、Revit、ArcGIS这些软件,说明很多搞工业软件二次开发的人都有跨软件经验的诉求。我自己的体会是,从其他CAD软件转过来做AM开发,最需要调整的是对“数据模型”的认识。
像Creo/NX这些传统CAD软件,二次开发的核心往往是操作几何:拉伸、旋转、约束、草图,因为它们的模型本质是特征树与几何构建历史。但AM的核心是设计对象加属性,几何只是一个展示结果。你用AM的API能非常方便地遍历“这个区域有哪些管道、它们的口径是多少、连接方式是什么”,但你要像NX Open那样去改一个管道的几何形状,反而没那么直接。
这其实是AM二次开发的一个优势。船厂真正需要自动化的大量工作,恰恰集中在属性处理和对象组织层面:材料统计、编码维护、标准检查、报表输出。所以C#在AM开发里的角色,更多的像是一个“数据管家”,而不是几何建模器。想明白这一点,学习方向就不会跑偏。
3. 第一个完整实操:批量修改管道属性
3.1 需求拆解与实现步骤
入门阶段,我推荐做一个能覆盖大多数核心API要素的小功能:批量修改选中管道的压力等级属性。为什么选这个?因为它涉及了元素获取、属性读写、批量遍历、事务提交这几个关键环节,麻雀虽小五脏俱全。做完这个,后面的复杂功能基本都是往这个框架上叠加逻辑。
先明确一下需求。操作者在AM中预先框选了一批管道,然后运行插件,输入一个新的压力等级值,程序自动把选中管道对应的属性修改成新值。
实现步骤分为以下几步:
- 在Visual Studio中新建一个C#类库项目,目标框架按AM版本选择,建议.NET Framework 4.x。
- 引用AM安装目录下的核心API程序集,同时设置“Copy Local”属性为False。
- 编写插件类,继承接口,实现界面菜单的注册。
- 编写数据访问逻辑:获取当前选择元素、遍历过滤管道对象、读取原属性、写入新属性。
- 配置AM的启动加载文件,让插件在AM启动时被识别和加载。
- 编译启动,在AM里选中管道实测。
3.2 程序集的引用与加载配置
新建项目后,马上就会遇到引dll这件事。AM的API相关程序集在安装目录下,路径一般长这样:C:\AVEVA\Marine\...\System或者类似的结构目录。里面能找到用于界面扩展和数据库访问的DLL文件。
这里要特别强调一个新手最容易踩的坑:**不要把引用的DLL直接拷贝到自己的项目输出目录,也就是Copy Local要设为False。**因为这些DLL本身是AM客户端在启动时才会正常加载的,它们之间的依赖关系由AM自己的启动器管理。如果你的程序输出目录里多出来一份同名DLL,运行时经常会出现程序集版本冲突,报错信息五花八门,非常难查。
正确做法是在“引用管理器”里浏览找到AM安装目录下的原始DLL,然后选中每个引用,在属性面板把“复制本地”设置成False。这样编译出的插件DLL体积小,运行时也使用的是AM自身加载的那份,不会出现版本打架。
3.3 编写插件主体与数据读写逻辑
下面的代码是一个贴近实际风格的入门示例。因为AM不同版本的命名空间和接口细节会有差异,这里给出的是逻辑模板,你拿到自己的版本上对照调整即可。
using System; using System.Windows.Forms; using Aveva.ApplicationFramework; using Aveva.Core.Database; namespace SimpleAmPlugin { public class SimplePlugin : IPlugin { public string Name => "SimplePipeAttributeUpdater"; public string Description => "批量修改选中管道的压力等级"; private Command _command; public void Start(IServiceManager serviceManager) { _command = new Command("ChangePressure", "修改压力等级", ChangePressure); CommandBar commandBar = serviceManager.CommandBarManager.CommandBars["Main"]; commandBar.Controls.Add(_command.Button, "修改压力等级"); } public void Stop() { // 插件停止时的清理逻辑,一般不需要处理 } private void ChangePressure() { string newPressure = Microsoft.VisualBasic.Interaction.InputBox( "请输入新的压力等级名称", "修改压力等级", "", -1, -1); if (string.IsNullOrWhiteSpace(newPressure)) { MessageBox.Show("未输入有效的压力等级。"); return; } int updateCount = 0; // 获取用户当前在AM中选择的元素集合 DbElement[] selectedElements = GetCurrentSelection(); foreach (DbElement element in selectedElements) { // 判断是否为管道类型,这里要按AM中的类型常量来过滤 if (IsPipeElement(element)) { DbAttributeType attrType = DbAttributeType.GetAttributeType("PresSpec"); element.SetAttribute(attrType, newPressure); updateCount++; } } // 提交修改到数据库 DbContext.Commit(); MessageBox.Show($"修改完成,共处理 {updateCount} 根管道。"); } } }真实项目中,获取当前选择元素通常会走AM提供的当前Element集合接口,过滤也经常会用到类型判断。由于版本差异,我特意用注释标注了需要按本机版本调整的地方。这套结构帮你理清了思路:界面入口、数据遍历、条件过滤、属性写入、统一提交。
需要特别提醒一个重要的操作习惯:**写好的批量修改程序,第一次务必在测试项目里验证,不要直接在生产项目数据库上跑。**万一过滤条件写错了,把不该改的构件全改了,恢复起来非常麻烦。我见过有人批量改编码把整个系统里的管道等级全部覆盖成同一个值,最后只能靠备份恢复。
3.4 注册插件到AM启动加载流程
写完代码只是第一步,要让AM运行的时候加载你的插件,还需要做启动配置。AM通常是通过配置目录下的XML文件来识别插件的。
常见做法是在AM安装目录下的配置XML文件里,新增一个插件定义节点,其中要写明程序集名称和插件类全名。具体文件和节点名称随版本变化较大,但在AM的安装配置目录下搜索已有的插件定义例子,照着里面已有的节点格式加一个就行,这是最稳的方法。
还有一种方式是通过AM的“Customize”功能在界面上注册菜单项,同时指定命令名称。这个方式的优点是操作直观,不需要手工改配置文件,但灵活性不如直接改XML。
这一步卡住的人很多,我的建议是:先找到一份能正常工作的现存插件配置,复制一份再修改。不要在没有任何参考的情况下凭空写XML节点,很容易漏掉必填项。
4. 调试技巧与常见问题排查实录
4.1 把Visual Studio附加到AM进程
入门阶段最常用的调试手段是“附加到进程”。步骤是先用VS打开插件源码,编译生成dll,确保XML里已经注册好插件,然后启动AM,等主界面起来后,回到VS里选择“调试”菜单下的“附加到进程”,在弹出的列表中找到AM的设计程序进程,点确定。
这里有一个很关键的小动作:附加的时候,在“附加到”那里要确认类型是“托管代码”。我遇到过一次很邪门的情况,怎么断点都命中不了,折腾半天发现VS默认附加到了本机代码,托管断点自然一个都不触发。
还有一个建议:在VS的“调试”菜单里,打开“异常设置”,勾选“Common Language Runtime Exceptions”。这样当代码抛异常时,VS会在第一时间定位到出错的代码行,而不是让AM弹一个难懂的英文错误框然后假装无事发生。这个习惯能帮你节省大量排查时间。
4.2 三个高频问题的排查思路
整理一下入门阶段最常遇到的几个问题,做成一个速查表,遇到直接照着排查就行。
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 编译报错,提示找不到类型或命名空间 | 引用的API程序集版本和实际版本不一致,或者缺少某个依赖程序集 | 核对AM版本,确保引用的是安装目录下的原始DLL,必要时用文本编辑器查看程序集版本 |
| AM启动后看不到插件菜单 | XML配置写错、插件类没有正确继承接口、程序集文件名和XML里写的不一致 | 检查配置节点的程序集名称是否是dll文件名,类名是否带完整命名空间,再打开AM的日志确认加载过程 |
| 代码执行时报“无法连接到数据库” | 数据库连接对象没有正确初始化,或者当前没有在AM中打开任何设计项目 | 确认先打开设计项目再运行插件,检查连接对象的初始化位置 |
| 修改属性后界面不刷新 | 数据已写入数据库但视图没有触发刷新 | 调用视图刷新方法,或者重新选中当前模型区域 |
| 程序集版本冲突 | 输出目录里Copy Local了多个版本一样的DLL | 把所有引用的Copy Local设为False,清理输出目录后重新编译 |
4.3 提升开发效率的几件小事
说几个我自己的经验。
第一,在项目里建一个“测试工具”类。专门放一些临时的小方法,比如“遍历当前选中元素并弹窗显示类型”,用来快速验证API调用是否成功。你别小看这个,很多时候你不确定一个接口怎么用,先写一个小方法跑一下看返回结果,比盯着文档猜快得多。
第二,善用AM的在线帮助和本地Help文档。AM的API文档通常随客户端一起安装在本地,系统里搜索有没有以“API帮助”命名的文件就行。不同版本的文档结构差异挺大,但只要能打开,这就是你最高效的参考。比在网上搜零散帖子靠谱。
第三,写批量操作代码时注意效率。如果要对几千个元素做逐条属性更新,每改一个就提交一次会非常慢。正确做法是:把所有修改放在内存里做,最后统一提交一次。这个和数据库批处理的思路一模一样,执行耗时能差出几十倍。
第四,一定要有“项目环境隔离”的意识。AM的项目数据库是一个多专业共享的库,你的插件一旦运行就会真实修改数据。无论是在开发阶段还是在交付阶段,都先在一个专用的测试项目里验证。等到功能稳定了,再放到生产环境使用。这不是怕麻烦,这是对自己和团队负责。
5. 进阶方向与后续学习路径
到了这一步,你已经完成了Aveva Marine C#二次开发从零到一的过程:搭好了环境,写出了一个能访问数据库、修改属性的插件,并且知道了怎么去调试和排查问题。接下来要往哪个方向走,取决于你所在的团队和岗位实际需要。
如果团队经常要做材料统计,下一步值得做的就是报表自动化。把AM中的管道、设备、阀门信息批量导出到Excel,然后按整船或分段维度汇总。这个功能在大多数船厂的需求度都很高,而且逻辑和属性读写是一脉相承的。
如果出图工作量大,可以研究出图自动化,比如自动生成管段图上的标注信息、自动更新图框中的项目名称和比例。这个方向会接触到AM的图纸对象和视图控制,API复杂度上去一个台阶,但价值也更明显。
如果要做标准化设计,可以在插入标准件时自动校验规格,不符合项目标准的直接拦截并提示。这个方向需要你对船厂设计标准有比较深的理解,但做出来的东西能直接影响设计质量。
我个人在实际操作中的感受是,AM二次开发的门槛不在于C#语法,也不在于API有多难,而在于你能不能把“业务需求”转换成“数据操作”。每次接到一个需求,先别急着写代码,花五分钟想清楚这几个问题:要操作的数据对象是哪些类型、这些对象的过滤条件是什么、哪些属性字段需要读写、是在界面交互里做还是后台批量跑。把这四条理清楚了,代码写起来就是水到渠成的事。
最后再分享一个小技巧:如果你接手的是别人留下来的AM插件,不要急着看懂所有代码,先找到它的启动入口和XML配置,摸清它的加载方式,再把代码里的命名空间和本机安装的API版本对照一下。很多旧插件跑不起来,不是因为代码逻辑错了,而是因为程序集版本和当前安装环境不匹配。调整好引用,代码原封不动也能跑起来。
这篇入门从一个批量改属性的小功能讲起,把AM二次开发最核心的链路走了一遍。后续我会再拆解更具体的场景,比如如何做Excel报表导出、如何实现自动出图、如何处理多区域批量操作。开发这事就是这样,第一个功能跑通了,后面的路自然就打开了。