版本声明
- 本篇基线为AVEVA E3D Design 3.1;前代产品统一写作AVEVA PDMS。
- 政策事实:自 2024 年 4 月 1 日起,AVEVA PDMS 不再销售、不再提供支持,研发投入全部转向 E3D Design。迁移路径包括本地或云端部署,也可作为 AVEVA Unified Engineering 的一部分交付;官方口径是 E3D Design 仍与 PDMS 后续版本兼容,客户可在两平台并行,PDMS 最终被淘汰。
- 必须如实交代的关键事实:官方并未给出"旧命名空间 → 新命名空间"的迁移对照表。社区帖中出现的对应关系(
Aveva.Pdms.PMLNet→Aveva.Core.PMLNet、Aveva.Pdms.Presentation→Aveva.Core.Presentation、Aveva.Pdms.Presentation.PDMSCommands→Aveva.Core.Commands)来源性质为社区,仅作线索,不得当作官方结论。- 版本纠错:15.x 不是 E3D Design 的版本,而是 AVEVA Engineering 的版本线。文档站同时列出 “E3D Design 3.1” 与 “Engineering 15.8”。E3D Design 未发现 15.x 命名。
- 本篇脚本为纯文本扫描与差异报表工具,不调用 AVEVA API;所有命中数量、文件数量一律为示意,真实值须在本机跑出。
一句话结论:PDMS 到 E3D 的定制迁移,最大的风险不是语法变了,而是旧程序集在新环境里根本不存在、而官方又没有给对照表——所以迁移的正确姿势是"扫描 → 分级 → 逐个验证",而不是"改个命名空间就交差"。
〇 认知问题
- PDMS 现在到底还能不能用?迁移是"必须做"还是"想做再做"?
- 我手上的定制资产,哪些能直接搬过去,哪些必须重写?
- 旧的程序集名(如
Pdms.Database.dll、PDMSFilters.dll)在 E3D Design 里对应谁?有没有官方对照表? - 社区帖里说的那些命名空间对应关系,能不能直接拿去批量替换?
- 迁移之后,我怎么向项目证明"行为没变"?
一 机制解析
1.1 政策背景:迁移窗口是真实存在的
先把政策事实摆清楚(来源:官方产品页与官方博客):
| 项 | 事实 |
|---|---|
| 停售与停支持 | 自 2024 年 4 月 1 日起,AVEVA PDMS 不再销售、不再提供支持 |
| 研发投入 | 全部转向AVEVA E3D Design |
| 迁移路径 | 本地部署或云端部署;亦可作为AVEVA Unified Engineering的一部分交付 |
| 并行期 | 官方称 E3D Design 仍与 PDMS 后续版本兼容,客户可在两个平台并行推进 |
| 终局 | PDMS 最终被淘汰 |
第 1 个认知问题的答案是明确的:PDMS 还能用,但"不再销售、不再提供支持"意味着新问题不会再有官方补丁;迁移是必答题,只是答得早晚而已。而"在并行期迁移"恰恰是最有利的时间窗——两个平台都在,可以用来做对照验证,这也是本篇强调"逐个验证"的现实基础。
1.2 三类迁移资产,成本差异极大
定制代码要迁移的资产分三类,迁移成本从低到高:
| 资产类别 | 典型内容 | 迁移成本 | 主要风险 |
|---|---|---|---|
| ① PML 宏 / 函数 / 表单 | .pmlfnc、.pmlfrm、.pmlobj | 低 | 语言本身跨代基本延续,风险在"引用了什么数据/命令" |
| ② PML.NET 程序集 | 用PMLNetCallable暴露给 PML 的 .NET 类 | 中 | 程序集名与命名空间换代,加载路径与验证方式要重做 |
| ③ .NET Addin | 实现IAddin的 CAF 插件、命令类、UIC | 高 | 程序集全换代 + 装载配置 + 界面机制(command ribbon)三重变化 |
第 2 个认知问题的答案一句话概括:
PML 资产是"搬",PML.NET 资产是"改",.NET Addin 资产是"重建"(至少要重新验证装载与界面两块)。
原因是三层技术依赖的稳定性不同:PML 语法本身是语言层,跨代延续性最好;PML.NET 依赖程序集与命名空间;.NET Addin 除了依赖程序集,还依赖装载配置文件(<模块名>Addins.xml)与界面机制(.uic与命令Key),而界面机制正是官方明确指出"旧式方式仍受支持但不推荐、与 command ribbon 不兼容"的地方。
1.3 程序集与命名空间的代际差异
可核实的差异如下(来源:官方 NCUG 与历史版本文档):
| 代 | 数据库程序集 | 过滤器程序集 |
|---|---|---|
| PDMS 12.0 时代 | Pdms.Database.dll | PDMSFilters.dll |
| E3D Design 3.1 | Aveva.Core.Database.dll | Aveva.Core.Database.Filters.dll |
E3D Design 3.1 侧可用的核心程序集还包括:Aveva.ApplicationFramework.dll、Aveva.ApplicationFramework.Presentation.dll、Aveva.Core.Geometry.dll、Aveva.Core.Maths.Geometry.dll、Aveva.Core.Shared.dll、Aveva.Core.Utilities*.dll、Aveva.Core3D.Graphics.dll、Aveva.Engineering.Tags.Pml.dll;Standalone 程序集为Aveva.Core3D.Standalone、Aveva.E3D.Standalone。
关键观察:旧名Pdms.Database.dll与新名Aveva.Core.Database.dll之间,“Pdms” 与 “Core” 的替换看起来天经地义,但PDMSFilters.dll→Aveva.Core.Database.Filters.dll就不是简单替换(还多了.Database这层)。一键替换在这里立刻失效——这就是第 3 个认知问题的答案:
旧程序集在 E3D Design 里"对应谁",官方没有公开对照表;只能逐个去实际安装目录里确认该程序集是否存在。
1.4 官方没有对照表,社区说法怎么用
第 4 个认知问题是本篇最重要的一条纪律。事实是:
- 官方未提供PDMS → E3D 的命名空间/程序集迁移对照表(本次调研在官方文档渠道中未找到);
- 社区帖提到的三条对应关系是:
Aveva.Pdms.PMLNet→Aveva.Core.PMLNetAveva.Pdms.Presentation→Aveva.Core.PresentationAveva.Pdms.Presentation.PDMSCommands→Aveva.Core.Commands
这三条只能当线索,不能当结论。使用纪律有四条:
- 不批量替换。按线索逐个替换、逐个编译、逐个运行验证;
- 不写进项目规范。项目规范里只能写"已验证存在的程序集与命名空间"清单,不能写"社区说应该等于……";
- 验证方式唯一:在本地 E3D Design 环境的安装目录里找出该程序集文件是否存在,再用反射/IntelliSense 确认类型是否存在;
- 把验证结果落表。每验证一条就登记一条,最终这份表就是你项目的"私人对照表"——它比任何网上流传的表都可靠。
另外要牢记系列铁律 2:混合开发前先确认产品版本,Aveva.Pdms.*与Aveva.Core.*是两代命名空间,官方未给迁移表,只能逐个验证。
1.5 迁移的四个阶段
| 阶段 | 目标 | 产出 | 完成判据 |
|---|---|---|---|
| A 清点 | 知道有哪些资产 | 资产清单(文件级) | 文件数与仓库对得上 |
| B 扫描 | 找出所有"代际敏感"的引用 | 命中清单(行级) | 每处命中都有风险等级 |
| C 分级改造 | 按风险等级处理 | 改造后的代码 + 验证记录 | 每处命中都有"已改/已证/已弃"结论 |
| D 回归验证 | 证明行为未变 | 对照测试记录 | 既定用例全部通过 |
四阶段里,B 阶段的扫描器是全流程的性价比之王:它不依赖任何 AVEVA API,纯文本就能跑,却能把"埋在几千个文件里的旧引用"一次性挖出来。
1.6 回归测试设计:等价性优先
第 5 个认知问题的答案是"对照测试"。设计要点三条:
- 黄金样本:在 PDMS 环境里把关键场景的输出(清单、报表、日志)保存下来,作为"黄金样本";
- 同输入同输出:在 E3D 环境里跑同一批输入,把输出与黄金样本逐行比对;
- 差异必须可解释:任何差异都要落到"预期内"或"缺陷"二选一,不允许"大致相同"。
其中第二条要特别注意一个陷阱:输出里的时间戳、路径、版本号必然不同,比对前要先把这些字段规范化掉,否则比对结果全是噪声。
二 完整代码与逐行剖析
2.1 迁移自查器:旧引用扫描脚本
这段脚本扫描定制代码仓库里的代际敏感字符串,输出一份差异报表。它不调用任何 AVEVA API,因此在迁移开始前就能跑——这是全流程里唯一"零依赖、可立刻上手"的一步。
# scan-legacy.ps1 —— PDMS → E3D 定制迁移自查器(只读扫描)param([Parameter(Mandatory = $true)][string]$Root,# 代码仓库根目录[Parameter(Mandatory = $true)][string]$OutCsv# 输出:命中清单 CSV)# 扫描规则:每条 = 一个"代际敏感"特征# 注意:这里是"发现线索",不是"判定结论";# 社区流传的命名空间对应关系只作线索,必须逐个在本机验证。$rules= @(@{Type='旧数据库程序集';Rx ='(?i)\bPdms\.Database\.dll\b'},@{Type='旧过滤器程序集';Rx ='(?i)\bPDMSFilters\.dll\b'},@{Type='旧命名空间';Rx ='(?i)\bAveva\.Pdms\.[A-Za-z0-9_.]*'},@{Type='旧命令命名空间';Rx ='(?i)\bAveva\.Pdms\.Presentation\.PDMSCommands\b'},@{Type='版本号误标';Rx ='(?i)\bE3D\s*1[5-9]\.[0-9]'},@{Type='硬编码安装路径';Rx ='(?i)[A-Z]:\\[^:]*\\(AVEVA|Cadcentre|Program Files)'})# 覆盖 PML 与 .NET 两侧的常见文件类型# (PML 侧扩展名清单与第三方 PML 语言服务支持的扩展名一致,见参考文献第三方资源说明)$exts='*.pml','*.pmlfnc','*.pmlfrm','*.pmlobj','*.pmlmac','*.pmlcmd','*.cs','*.xml'$hits=foreach($ein$exts){Get-ChildItem-LiteralPath$Root-Recurse-File-Filter$e-ErrorAction SilentlyContinue|ForEach-Object{$file=$_$ln= 0foreach($linein(Get-Content-LiteralPath$file.FullName-Encoding UTF8)){$ln++foreach($rin$rules){if($line-match$r.Rx){[pscustomobject]@{文件 =$file.FullName.Substring($Root.Length).TrimStart('\')行号 =$ln命中类型 =$r.Type命中原文 =$Matches[0]风险等级 =if($r.Type-in@('旧数据库程序集','旧过滤器程序集','旧命名空间','旧命令命名空间')){'高'}else{'中'}结论 ='待验证'# 一律初始为待验证,禁止直接标"已改"}break# 同一行只记第一条命中,避免噪声}}}}}$hits|Export-Csv-LiteralPath$OutCsv-NoTypeInformation-Encoding UTF8$summary=$hits|Group-Object命中类型|Sort-ObjectCount-Descending|Select-ObjectName,Count"命中总数:$($hits.Count)"$summary|Format-Table-AutoSize2.2 逐行剖析
为什么是"扫描文本"而不是"解析代码"?
因为迁移期最需要的是广度而不是精度:解析器只能处理语法正确的代码,而真实迁移中最麻烦的恰恰是"语法有问题、早已没人维护"的老脚本。纯文本扫描能把这些一起捞出来。
@{ Type = …; Rx = … }规则表
把"要查什么"与"怎么查"分离成数据,是让这个脚本能持续演进的关键。以后发现新的代际敏感特征(例如某个界面类名),往规则表里加一行即可,不用改逻辑。
(?i)\bPdms\.Database\.dll\b(?i)忽略大小写(旧代码里字符串大小写常不一致);\b词边界避免匹配到XxxPdms.Database.dll这类误命中;把.转义为\.以保证按字面匹配。
(?i)\bAveva\.Pdms\.[A-Za-z0-9_.]*
这条是最关键的线索收集规则。它不假设任何对应关系,只把Aveva.Pdms.*家族全部列出——因为社区线索里三条对应关系远远覆盖不了真实代码里出现过的所有Aveva.Pdms.*命名空间。先列出全部,再逐个验证。
(?i)\bE3D\s*1[5-9]\.[0-9]
这条规则本身就是一处事实纠错的固化:15.x 不是 E3D Design 的版本,而是 AVEVA Engineering 的版本线。老代码或老注释里若写了"E3D 15.x",说明其版本认知本身就是错的,迁移时必须一并纠正。
(?i)[A-Z]:\\[^:]*\\(AVEVA|Cadcentre|Program Files)
硬编码安装路径是迁移期最容易被低估的坑:代码在新机器上"能编译但在错误的位置找东西"。这条规则把这类路径挖出来,提醒改用环境变量(如AVEVA_DESIGN_EXE、CAF_ADDINS_PATH)。
$exts里的扩展名清单
PML 侧的.pml / .pmlfnc / .pmlfrm / .pmlobj / .pmlmac / .pmlcmd与第三方 PML 语言服务扩展所支持的扩展名集合一致(来源性质:第三方资源说明,非官方清单)。覆盖这些扩展名,是为了不漏掉宏文件和命令文件。
break(同一行只记第一条命中)
一行里同时命中多条规则时只记第一条,否则命中清单会被噪声淹没。迁移清单的第一要求是"能被人看完"。
结论 = '待验证'
所有命中一律初始化为"待验证"。这是刻意的机制设计:不允许出现"扫描完就直接标已改"的流程,因为扫描器只负责发现线索,不负责判定正确性(系列铁律 2)。
2.3 差异报表结构
扫描产出只是原料,要变成可执行的迁移计划还得加工成下面这张表:
| 文件 | 行号 | 命中类型 | 命中原文 | 建议动作 | 风险等级 | 结论 | 验证记录 |
|---|---|---|---|---|---|---|---|
…/ModelUtil.cs | 42 | 旧数据库程序集 | Pdms.Database.dll | 查新环境是否存在同名/对应程序集 | 高 | 待验证 | — |
…/menu.uic | 8 | 旧命令命名空间 | Aveva.Pdms.Presentation.PDMSCommands | 按线索试Aveva.Core.Commands,再验证 | 高 | 待验证 | — |
…/report.pmlfnc | 15 | 硬编码安装路径 | C:\Program Files\AVEVA… | 改用环境变量 | 中 | 待验证 | — |
三条填写纪律:
- "结论"只能取四值:
已改、已验证未改、已废弃、待验证。"大概改好了"不是结论。 - "验证记录"必须写清怎么验的:在哪台机器、哪个版本、用哪个操作、看到什么结果。
- 风险等级允许上调不允许下调:拿不准的往"高"放,宁可多验一遍。
2.4 迁移风险分级表
| 等级 | 特征 | 处置 |
|---|---|---|
| 高 | 出现旧程序集名、旧命名空间、旧命令命名空间 | 必须逐个在本机验证存在性后再改;不允许批量替换 |
| 中 | 硬编码路径、版本号误标、注释里的旧信息 | 可批量处理,但改完要抽查 |
| 低 | 纯 PML 语法、无外部引用 | 直接搬,跑一遍原用例即可 |
这张表的作用是分配时间:把 80% 的验证精力放在"高"档上,因为只有它会造成"编译通过但运行期加载失败"这类最难查的问题。
2.5 回归测试用例设计
| # | 用例 | 输入 | 期望输出 | 比对方式 |
|---|---|---|---|---|
| 1 | 数据巡检 | 指定 ZONE | 元素清单(名称+类型) | 与黄金样本逐行比对 |
| 2 | 批量改名 | 已知命名冲突集 | 改名前后对照表 | 逐行比对 |
| 3 | 报表导出 | 指定报表定义 | 表格字段与行数 | 字段名全等、行数相等 |
| 4 | 规则校验 | 已知含缺陷样本 | FAIL清单 | 失败集合完全相等 |
| 5 | 界面挂载 | 从菜单/工具栏触发 | 命令可执行且状态正确 | 人工确认 + 日志一致性 |
| 6 | 装载验证 | 冷启动一次 | Addin 与 PML Add-in 均加载 | 日志中出现装载记录 |
比对前必须做规范化:剔除时间戳、路径、版本号,统一换行符与大小写敏感度。否则比对结果全是噪声,等于没比。
三 常见报错与排查
现象 1:代码能编译,但运行期报"找不到程序集/无法加载类型"。
- 原因候选:引用的旧程序集(如
Pdms.Database.dll、PDMSFilters.dll)在新环境里根本不存在——这正是迁移的最大风险点。 - 处置:到本地 E3D Design 安装目录实际查找该程序集文件;不存在就换用已确认存在的对应程序集(如
Aveva.Core.Database.dll、Aveva.Core.Database.Filters.dll),改完重新编译并运行验证。不要用命名空间替换去"猜"程序集名。
现象 2:USING NAMESPACE报解析失败。
- 原因候选:写了"部分命名空间"。官方机制明确:
USING NAMESPACE '<string>'指定命名空间时大小写不敏感,但不允许书写部分命名空间(写父级命名空间再取子对象会报错)。 - 处置:一次写全整条命名空间路径。迁移期特别容易犯这个错,因为旧代码里的命名空间层级与新代码不同。
现象 3:PML 宏在新环境下"什么都没做",也不报错。
- 原因候选一:PML 错误机制——错误不会立即报错,是否输出取决于下一行输入;没有匹配的
handle命令时,错误表现会非常隐晦; - 原因候选二:宏依赖的某个命令/对象在新版本下语义不同。
- 处置:在关键步骤前后插"心跳"输出,逐段缩小范围;不要以"没报错"作为迁移成功的证据。
现象 4:.NET Addin 完全不加载,界面上什么都没有。
- 原因候选一:装载配置文件名不对——每个 CAF 应用有各自的
<模块名>Addins.xml(例如 MODEL 对应DesignAddins.xml); - 原因候选二:文件位置不对(默认与可执行文件同目录,可用
CAF_ADDINS_PATH覆盖,支持;分隔多路径与 UNC 路径); - 原因候选三:程序集里没有实现
IAddin的类(CAF 是反射查找这样一个类,不是靠配置声明)。 - 处置:按上面三条逐一核对;开发期打开
AVEVA_CAF_TRACING看装载跟踪。
现象 5:界面挂上了,但菜单/工具栏项点了没反应。
- 原因候选:
.uic靠命令对象的Key关联,若命令类构造函数里没有设置Key,关联就断了(系列铁律 5)。 - 处置:确认命令类在构造时设置了
Key,且.uic中的键与之完全一致;同时确认模块级<模块名>Customisation.xml已把该.uic列入(注意其中的$1会被当前工程名替换)。
现象 6:迁移文档里写着"E3D 15.x"。
- 原因候选:版本认知错误。15.x 是 AVEVA Engineering 的版本线,不是 E3D Design 的。
- 处置:改为 E3D Design 3.1(本系列基线);同时用 2.1 脚本的"版本号误标"规则全文扫一遍,把这类错误一并纠正。
四 动手练习
练习 1(清点,判定标准:文件数与仓库对得上)
列出你的定制资产清单,按三类(PML / PML.NET / .NET Addin)分组。判定标准:每组文件数之和等于仓库内相关文件总数,且每个文件都归属到某一组。
练习 2(扫描,判定标准:每条命中都有风险等级)
用 2.1 的脚本扫描你的仓库。判定标准:输出的 CSV 中每行都有"命中类型"与"风险等级",且命中总数的分组统计能打印出来。
练习 3(逐个验证,判定标准:至少验证三条)
从命中清单里挑"高"档的三条,到本地 E3D Design 环境逐个验证(程序集是否存在、类型是否可用)。判定标准:三条都在"验证记录"列写明了机器、版本、操作与结果,且结论只取四值之一。
练习 4(对照测试,判定标准:六条用例全部有结论)
按 2.5 的表格设计 6 条对照测试用例(可以只用其中 3 条真正跑通)。判定标准:每条用例都有输入、期望输出与比对方式,且比对前做过时间戳/路径规范化。
练习 5(纪律自查,判定标准:零批量替换)
检查你的迁移记录里有没有"批量替换命名空间"的操作痕迹。判定标准:若存在,必须能举证每一处的验证记录;举证不出的,一律改回"待验证"。
五 小结与下一篇预告
本篇三句话:
- PDMS 自 2024 年 4 月 1 日起不再销售、不再提供支持,迁移是必答题;并行期是最好的验证窗口。
- 三类资产迁移成本递增:PML 是"搬",PML.NET 是"改",.NET Addin 是"重建"(装载与界面两块都必须重验)。
- 官方没有命名空间迁移对照表,社区说法只是线索——所以流程必须是"扫描 → 分级 → 逐个验证",扫描器只负责发现线索,不负责判定正确性。
到这里,19 篇的技术件已经齐了:语言(PML1/PML2)、界面(Command + UIC)、数据(DbElement)、桥接(PML.NET)、出图报表、元件库、规则检查、应力对接、批量作业、迁移。但它们还是一堆散件。
第 20 篇《收官项目:E3D 二次开发工具箱》把它们组装成一个可运行的整体:环境自检器、PML 代码库、命令与 UI 挂载、数据访问层、批量调度与日志、迁移自查器六个模块,给出目录结构、模块职责、接口契约与上线检查清单,并附一次完整的端到端运行记录(其中的数值是占位,真实值必须在你自己的机器上跑出来)。
文末 FAQ
FAQ 1:PDMS 现在还能不能用?迁移是必须的吗?
能用,但官方口径是:自 2024 年 4 月 1 日起,PDMS 不再销售、不再提供支持,研发投入全部转向 E3D Design。迁移路径包括本地或云端部署,也可作为 AVEVA Unified Engineering 的一部分交付;官方称 E3D Design 仍与 PDMS 后续版本兼容,客户可以在两个平台并行推进,PDMS 最终被淘汰。所以迁移是必答题,只是时间早晚;而在并行期内两侧都在,正好可以用来做对照验证,是最有利的迁移窗口。
FAQ 2:我的定制资产里,哪些能直接搬,哪些必须重写?
按三类看:PML 宏/函数/表单(.pmlfnc、.pmlfrm、.pmlobj)迁移成本低,语言层跨代延续性好,重点是排查它引用了什么数据与命令;PML.NET 程序集成本中等,因为程序集名与命名空间换代,加载与验证方式要重做;.NET Addin成本最高,因为除了程序集换代,还要重做装载配置(<模块名>Addins.xml)与界面机制(.uic与命令Key),而界面机制正是官方指出旧式方式"仍受支持但不推荐、与 command ribbon 不兼容"的地方。一句话记法:PML 是搬,PML.NET 是改,.NET Addin 是重建。
FAQ 3:旧程序集名在 E3D 里对应谁?有官方对照表吗?
官方没有给出旧→新的命名空间/程序集迁移对照表。可核实的两代差异举例是:PDMS 12.0 时代的Pdms.Database.dll、PDMSFilters.dll,对应 E3D Design 3.1 侧可用的Aveva.Core.Database.dll、Aveva.Core.Database.Filters.dll。注意这两组并不是简单替换:第二组多了.Database这一层,说明"一键替换"的做法从一开始就站不住。正确做法是到本地 E3D Design 的安装目录里逐个确认程序集文件是否存在、类型是否可用,并把验证结果登记成你自己的对照表。
FAQ 4:社区帖里的命名空间对应关系能直接用吗?
只能当线索。社区提到过Aveva.Pdms.PMLNet→Aveva.Core.PMLNet、Aveva.Pdms.Presentation→Aveva.Core.Presentation、Aveva.Pdms.Presentation.PDMSCommands→Aveva.Core.Commands,来源性质是社区,不是官方结论。使用纪律有四条:不做批量替换,只逐个替换逐个验证;不写进项目规范(规范里只写已验证存在的清单);验证方式唯一——在本机安装目录确认程序集存在、并用反射或 IntelliSense 确认类型存在;每验证一条就登记一条。另外真实代码里的Aveva.Pdms.*家族远比这三条多,所以扫描器应先列出全部,再逐条验证。
FAQ 5:迁移之后怎么证明"行为没变"?
做对照测试,核心是"同一批输入、同一套输出"。三步:一是在 PDMS 环境里把关键场景的输出(元素清单、报表、日志)保存为黄金样本;二是在 E3D 环境里跑同一批输入,与黄金样本逐行比对;三是任何差异都必须判为"预期内"或"缺陷"之一,不允许"大致相同"。比对前必须先规范化:剔除时间戳、安装路径、版本号,统一换行符。此外要特别提醒两句:USING NAMESPACE必须一次写全、不允许写部分命名空间,否则报解析失败;PML 的错误不会立即报错,是否输出取决于下一行输入,所以"没报错"绝对不能当作迁移成功的证据。