概述

  AVEVA PDMS(Plant Design Management System)是一种专业的三维设计和建模软件,主要用于工程项目的设计、建模和管理。它是针对工厂和工艺设施设计的领先软件之一,广泛应用于石油、天然气、化工、能源等行业。以下是一些主要特点和功能:

  • 三维建模和设计 :PDMS提供强大的三维建模能力,允许工程师和设计师创建复杂的工厂和设施模型。它支持多种对象类型和管道设计。
  • 智能对象 :PDMS中的对象具有智能化特性,能够自动关联和调整,使得设计变更时能够快速反映在整个模型中。
  • 工程设计集成 :PDMS能够与其他工程设计软件集成,如工艺流程模拟软件和结构分析软件,实现工程设计的全面协调。
  • 项目管理 :通过PDMS,项目团队可以协同工作,管理设计进度、资源分配和成本控制等项目管理任务。
  • 自定义和二次开发 :PDMS支持自定义功能和二次开发,使得用户可以根据特定需求扩展和定制软件功能。
  • 可视化和报告 :PDMS提供丰富的可视化和报告功能,支持生成各种设计和管理报告,帮助用户进行决策和沟通。

用户手册

  Pdms有很多的版本,以下教程采用的Pdms版本为Pdms12.1.SP2。Pdms的用户手册集成在Pdms软件中,只要安装好Pdms软件即可查看,具体步骤如下:

  1. 运行Pdms软件(双击Pdms安装路径下的pdms.bat文件即可运行)
  2. 点击Help菜单栏,选择Contents菜单项,会打开User Guides AVEVA Plant窗口
  3. 在目录中依次展开Customisation.NET CustomisationUser Guide,此部分介绍了Pdms的.NET二次开发
  4. Pdms还提供了对应的实例Demo项目,存放在Pdms安装目录下的Samples.zip压缩包文件中

编写第一个插件

创建项目

  因为Pdms的版本比较旧,因此本项目采用的目标框架为.net framework3.5。但是本人不喜欢.net framework中复杂且冗长的.csproj文件,因此我喜欢创建.net core项目再手动将TargetFramework目标框架改为net35,从而获得一个简洁的.csproj文件。同时在后续方便轻松的实现一键切换依赖的Pdms版本。

.net core项目最高版本为.net core3.1,之后的版本统称为.net(从.net5开始)

  1. 新建.NET Core.NETWPF应用程序(这里采用的是.NET6项目),取名为PdmsLibrary
  2. 双击项目名称,进入PdmsLibrary.csproj文件;修改目标框架,如下所示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <Project Sdk="Microsoft.NET.Sdk">

    <ProjectGroup>
    <!-- 将WinExe改为Library(将Windows应用程序改为类库项目) -->
    <OutputType>Library</OutputType>
    <!-- 将.net6.0-windows 改为 net35 (目标框架改为.net framework3.5) -->
    <TargetFramework>net35</TargetFramework>

    <!-- 去掉如下配置,.net framework3.5没有这些配置 begin -->
    --- <Nullable>enable</Nullable>
    --- <ImplicitUsings>enable</ImplicitUsings>
    <!-- 去掉如上配置,.net framework3.5没有这些配置 end -->

    <!-- 对WPF程序的支持 -->
    <UseWPF>true</UseWPF>

    <!-- 添加对Winform程序的支持 -->
    +++ <UseWindowsForms>true</UseWindowsForms>

    </ProjectGroup>

    </Project>
  3. App.xaml文件的属性生成操作从应用程序定义改为。此时App.xaml会被移除(没有删除),可通过添加现有项找回,目的是想像开发WPF应用程序一样可在App.xaml中声明应用资源

引用Pdms程序程序集

  1. 在Pdms的安装目录下找到Pdms如下程序集

    • Aveva.ApplicationFramework.dll
    • Aveva.ApplicationFramework.Presentation.dll
  2. 在项目目录下新建名为packages的目录,然后在packages目录下以Pdms的版本名新建一个目录,例如PDMS12.1.SP2,将程序集复制到packages\PDMS12.1.SP2目录

  3. 项目添加程序引用,选择浏览找到packages\PDMS12.1.SP2目录,将程序集添加为引用,引用成功后,可在.csproj文件中看到如下

    1
    2
    3
    4
    5
    6
    7
    8
    <ItemGroup>
    <Reference Include="Aveva.ApplicationFramework">
    <HintPath>..\packages\PDMS12.1.SP2\Aveva.ApplicationFramework.dll</HintPath>
    </Reference>
    <Reference Include="Aveva.ApplicationFramework.Presentation">
    <HintPath>..\packages\PDMS12.1.SP2\Aveva.ApplicationFramework.Presentation.dll</HintPath>
    </Reference>
    </ItemGroup>

编写插件

  现在,我们已经搭建好了Pdms的开发环境,接下来编写第一个HelloWorld程序。

定义命令

  定义一个命令用于处理按钮的点击事件。在项目中创建一个名为Commands的目录,在Commands目录下新建DisplayCommand.cs文件,内容如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Windows;
using Aveva.ApplicationFramework.Presentation;

namespace PdmsLibrary.Commands
{
public class DisplayCommand : Command
{
public DisplayCommand()
{
// Key不允许同名
this.Key = this.GetType().FullName;
}

// 重写事件的执行函数逻辑
public override void Execute()
{
MessageBox.Show("Hello World For Pdms!");
}
}
}

编写Addin

  为将WPF类库项目改造成同WPF应用类似的效果,这里将App.xaml.cs文件作为Pdms插件的**Addin**文本,打开App.xaml.cs文件,编写如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using Aveva.ApplicationFramework;
using System.Windows;

namespace PdmsLibrary
{
public partial class App : Application, IAddin
{
// 插件名称
public string Name => "PdmsLibrary";

// 插件描述
public string Description => "My First Pdms Library";

// 应用命令栏名称
public const string AppCommandBarName => "PdmsLibraryCommandBar";

// 插件加载时的入口函数
public void Start(ServiceManager serviceManager)
{
// 命令管理器
CommandManager commandManager = (CommandManager)serviceManager.GetService(typeof(CommandManager));
// 命令栏管理器
CommandBarManager commandBarManager = (CommandBarManager)serviceManager.GetService(typeof(CommandBarManager));

// 定义自定义命令
DisplayCommand displayCommand = new DisplayCommand();

// 将自定义命令添加到命令管理器中(非必须)
commandManager.Commands.Add(displayCommand);
// 在命令栏集合中添加一个新的命令栏
CommandBar commandBar = commandBarManager.CommandBars.AddCommandBar(AppCommandBarName);

// 向工具库集合中添加一个新的按钮
ButtonTool button = commandBarManager.RootTools.AddButtonTool(displayCommand.Key,"Button",null,displayCommand);
// 在新添加的命令栏上添加这个按钮
commandBar.Tools.AddTool(button.Key);
}

// Pdms退出时的回调函数
public void Stop()
{

}
}
}

载入插件

  1. 选择解决方案重新生成解决方案,保证没有语法错误,生成动态链接库

  2. 在资源管理器中,打开生成的dll文件目录,例如:D:/Codes/PdmsLibrary/bin/Debug/net35,复制资源管理器地址栏地址

  3. 打开Pdms安装路径,找到DesignAddins.xml文件,添加如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    <?xml version="1.0" encoding="utf-8"?>
    <ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- 在最下面添加如下内容 -->
    <!-- 这个路径指向D:/Codes/PdmsLibrary/bin/Debug/net35/PdmsLibrary.dll文件,省略.dll后缀; 这个路径可以是绝对路径或相对路径 -->
    <string>D:/Codes/PdmsLibrary/bin/Debug/net35/PdmsLibrary</string>

    </ArrayOfString>
  4. 成功载入我们写好的自定义插件后,启动Pdms程序就可以看到工具栏上多了一个名为"Button"的按钮,点击按钮弹窗显示:“Hello World For Pdms!”

一键切换Pdms版本

这里可以体现使用.NET CORE新的.csproj文件格式的优点

  1. 在项目的解决方案文件目录下新建名为directory.build.props文件,名为directory.build.props会被MSBuild自动加载

  2. 在解决方案下新建名为solution items的解决方案文件夹,并添加现有项将directory.build.props文件添加进来

  3. directory.build.props文件修改为如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <Project>
    <PropertyGroup>
    <!-- 定义一个名为PdmsVersion的变量表示Pdms版本,需同packages下目录同名 -->
    <PdmsVersion>PDMS12.1.SP2</PdmsVersion>

    <!-- 定义一个名为PdmsVersionForDefine的变量值为 将Pdms版本中的点替换为下划线 -->
    <PdmsVersionForDefine>$(PdmsVersion.Replace(".","_"))</PdmsVersionForDefine>

    <!-- 将PdmsVersionForDefine的值进行宏定义 -->
    <DefineConstants>$(PdmsVersionForDefine)</DefineConstants>
    </ProjectGroup>
    </Project>
  4. 打开.csproj文件,将PDMS.12.1.SP2替换为$(PdmsVersion),后续添加新的Pdms的dll引用版本位置也需要替换为$(PdmsVersion)。当前修改内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
     <ItemGroup>
    <Reference Include="Aveva.ApplicationFramework">
    <HintPath>..\packages\$(PdmsVersion)\Aveva.ApplicationFramework.dll</HintPath>
    </Reference>
    <Reference Include="Aveva.ApplicationFramework.Presentation">
    <HintPath>..\packages\$(PdmsVersion)\Aveva.ApplicationFramework.Presentation.dll</HintPath>
    </Reference>
    </ItemGroup>
  5. 现在只要维护PdmsVersion的值就能一键切换Pdms的版本了,同时如果在代码中存在版本的个性化差异,可通过条件编译实现差异

    1
    2
    3
    4
    5
    #if PDMS12.1.SP2
    Console.WriteLine("现在是PDMS12.1.SP2版本");
    #elif PDMS12_1_SP4
    Console.WriteLine("现在是PDMS12.1.SP3版本");
    #endif

调试插件程序

插件是运行在Pdms软件上,而不是独立运行的,因此,如果需要调试程序,需要附加到进程才能调试;

  • 插件是运行在Pdms软件上,而不是独立运行的,因此,如果需要调试程序,需要附加到进程才能调试;

  • 程序的运行速度很快,为了进行调试命中断点可通过如下方式阻塞程序运行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public void Start(ServiceManager serviceManager)
    {
    // 在插件的入口函数处,通过MessageBox阻塞程序的运行
    /*
    具体做法:
    1. 在入口函数通过弹窗阻塞程序往下运行,在弹窗的下面打上断点
    2. 将pdms附加到vs进程
    3. 关闭弹窗,即可发现命中断点

    附加进程:
    1. 运行pdms
    2. 点击vs中的调试菜单
    3. 选择附加到进程
    4. 在可用进程中找到名为 des.exe 的进程点击附加 (可使用筛选进程)
    */
    MessageBox.Show("Wait");
    }