概述
PDMS 的.NET开发主要分以下两种:
- .NET
- PML + .NET
.NET
AVEVA公司提供了.NET的二次开发接口,以方便有C#开发经验的工程师可以快速的利用.NET框架对AVEVA的产品进行开发,如PDMS,MARINE等。
传统的PDMS开发主要利用PML语言,但AVEVA提供的PML对象库有限,如果想实现更多丰富的功能,使用PML开发就有很大的局限性。但利用.NET可以方便的使用各种第三方接口和类库,也可以完成与其他各种软件的集成,有利于数据的管理和维护。
备注:
单纯的.NET开发和其他软件的.net开发,有相同的弊端。
- 开发调试效率低
- 插件的异常会导致PDMS的奔溃
IAddin接口
所有的AVEVA.NET插件都必须派生自IAddin接口,这也是AVEVA.NET插件与其他插件的不同之处。IAddin接口封装在
Aveva.ApplicationFramework.dl
l动态库中,因此在继承时,必须从
Aveva.ApplicationFramework
命名空间中进行引用,并且需要重写该接口。
该接口有2个属性和2个实例化方法,
IAddin
接口的原型声明如下:
string Description {get;}
string Name {get;}
void Start(ServiceManager serviceManager);
void Stop();
开发DLL
PDMS只接受动态库的方式作为接口。
建立项目
建立一个命名为HelloAddin的项目。
项目引用
Aveva.ApplicationFramework、Aveva.ApplicationFramework.Presentation
两个动态库。这两个动态库主要封装了程序框架插件、发布服务、程序设置以及菜单栏和标题栏的管理、命令对象、本地资源文件、主程序窗口、状态栏、MDI(多文档程序)、用户控件等属性方法的类
// 1.引入命名空间
using Aveva.ApplicationFramework;
using Aveva.ApplicationFramework.Presentation;
// 2.声明命名空间
namespace HelloAddin
{
// 3.声明类,必须继承IAddin接口
Public class HelloAddin : IAddin
{
// 4.重写IAddin接口的属性及函数.此处Start()函数是程序的入口函数,类似于普通C#程序中的Main函数。
public string Description
{
get {return "HelloAddin";}
}
public string Name
{
get {return "HelloAddin";}
}
public Void Start(ServiceManager serviceManager)
{
MessageBox.Show("Hello World");
}
public void Stop{}
}
}
编译项目
生成动态库文件,HelloAddin.dll文件。目前PDMS的12.0和12.1均只能接受FrameWork 3.5的版本,请勿使用高版本,会导致PDMS加载失败。
PDMS操作
拷贝动态库
将动态库拷贝到PDMS的根目录下,也可以拷贝到其他子目录,只要修改启动文件即可。
修改启动文件
我们如果想将刚才开发的HelloAddin,绑定在PDMS的Design模块启动程序的话。只需要修改DesignAddin.xml文件即可。
这个文件在PDMS的根目录下,如果是绑定Draft、Paragon等其他模块,只要修改模块对应的xml文件即可。
<?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">
<string>ExplorerAddin</string>
<string>HelloAddin</string>
</ArrayOfString>
如果不想把动态库放在根目录,可以建一个文件夹如:
mydevaddin
,放置我们的动态库。但xml需要同步改成
<string>mydevaddin/HelloAddin</string>
启动PDMS
运行界面如下图所示,当然这个程序并不能实现任何操作,仅仅是为了演示AVEVA.NET的实现过程。
API概述
.NET开发主要是利用AVEVA提供的各种类和接口对PDMS各个数据层次进行访问,包括图形用户界面(GUI),数据库(DATABASE),几何库(Geometry)等。所有的这些类和接口都被封装在多个不同的dll(动态链接数据库)中,这些dll主要可分为以下几大类:
说明 | dll文件 | 备注 |
---|---|---|
CAF(common application framework interface)通用程序框架接口 | Aveva.Application.Framework.dll | 该动态库主要封装了程序框架插件、发布服务、程序设置管理等属性方法的类 |
CAF(common application framework interface)通用程序框架接口 | Aveva.Application.Framework.Presentation.dll | 该动态库主要封装了菜单栏和标题栏的管理以及命令对象、本地资源文件、主程序窗口、状态栏、MDI(多文档程序)以及用户控件等属性方法的类 |
数据库接口 | Aveva.Pdms.Database.dll PDMSFilters.dll | 该动态库主要封装了与数据库有关联的操作 |
几何库接口 | AVEVA.Pdms.Geometry.dll | 该动态库主要封装了与几何计算相关的类 |
共享接口 | AVEVA.Pdms.Shared.dll | |
功能接口 | AVEVA.Pdms.Utilities.dll | 该动态库主要封装了消息、字符串、错误处理、追踪以及PML命令等类 |
图形接口 | AVEVA.Pdms.Graphics.dll | 该动态库主要封装了图形列表的相关类 |
PML + .NET
概述
PMLNET提供了在PDMS和.NET之间通信的服务。使用PMLNET可以实现以下三个功能:
- PML调用.NET中定义的对象和方法。
- PML在FORM中放置.NET中定义的控件。
- 在.NET中调用PML对象和方法。 数据匹配表:
PML | .NET |
---|---|
real | double |
string | string |
bool | bool |
array | hash table |
object | PMLNetCallable Class |
PML调用.NET方法
C#开发
动态库加载
添加PMLNET引用,引用PMLNET.dll动态库,并引用命名空间。
using Aveva.PDMS.PMLNet
建立类库
按常规C#类库的开发方法运作,修改
AsemblyInfo.cs
配置文件。
命名空间为
My.PMLNET
[PMLNetCallable()]
public class PMLNET
{
[PMLNetCallable()]
public PMLNET(){}
[PMLNetCallable()]
public void Assign(PMLNET that){}
[PMLNetCallable()]
public void MyMethod()
{
code
}
}
- 方法必须是公用的。
- 类必须有一个声明无参数的构造函数。
- 只能是类,不能是接口、结构等其他任意类型。
- Assign方法是必须的。
PML调用
将编译好的DLL文件,拷贝到PDMS根目录以下。
加载动态库
import '动态库的名称' // 动态库加载后,无法卸载,必须重启PDMS才能更新,非常麻烦。
// 引入命名空间
using namespace '空间名'
!pmlnet = object PMLNET()
!pmlnet.MyMethod()
特殊说明
PML调用.NET方法,如果传递的数据类型是数组,则.NET中对应的是哈希表。如果用foeach循环的话,顺序是混乱的。table中的键必须将double型的变量显示转换为object型。
public bool Update(Hashtable table)
{
for (int i = 1; i <= table.Count; i++)
{
string Guid = table[(object)double.Parse(i.ToString())].ToString();
}
}
如果对数组的顺序不敏感的话,也可以使用foreach循环
foreach(DictionaryEntry de in table)
{
string str = de.Key.Tostring();
}
PML调用.NET控件
C#开发
用户控件的开发流程,和用户方法的类似。在新建的时候,不是选择Class,而是选择UserControl
[PMLNetCallable]
public partial class DateTimeControl : UserControl
{
//构造函数
[PMLNetCallable]
public DateTimeControl()
{
InitializeComponent();
}
//固定写法
[PMLNetCallable]
public void Assign(DateTimeControl that)
{ }
//获取dataTime的选择结果
[PMLNetCallable]
public String GetDatePick()
{
string date = this.dateTimePicker1.Value.Year + "-" + this.dateTimePicker1.Value.Month + "-" + this.dateTimePicker1.Value.Day;
return date;
}
}
此处control类的名称有要求,不能是Control后面加数字的写法。比如不能为UserControl1,否则在PML调用时,会出现语法错误。PML在调用.NET类时候,类名也不能末尾是数字。
PML调用
窗体定义
// .NET控件必须被放置在一个容器中
FRAME .frmTest ''
using namespace '命名空间'
container .excont PmlNetControl 'Contol'
exit
// 定义一个成员变量
member .dateTime is DateTimeControl
// 构造函数
using namespace '命名空间'
!this.dateTime = object DateTimeControl()
// 调用Container控件的control方法,将其指定为成员变量的handle方法,这样PML就可以响应.NET的事件。
!this.excont.control = !this.dateTime.handle()
// 调用方法
!this.dateTime.GetDatePick()
// 调用事件,PML若想调用.NET的事件,必须先在.NET注册事件
!this.dateTime.AddEventHandler('OnPopup', !this, 'eventPML') // 注意事件方法是没有括号的。
SYSCOM
SYSCOM
也是一条PML命令,其用法和其他PML命令一样,只是其参数是Windows中的DOS命令。如在命令窗口中输入命令
syscom ‘dir’
,则可以在控制台窗口中显示出当前文件夹中的内容:
同理,输入
syscom ‘help’
则可以显示出常见DOS命令的使用说明:
由此可见,使用syscom相当于运行了一条DOS命令。因为DOS命令可以调用程序,如打开记事本,所以使用syscom也应该可以打开记事本。调用命令
syscom ‘notepad’
即可以了。
打开记事本后,可以看见PDMS程序处于等待状态。只有将记事本关闭,PDMS程序才恢复正常。如何使PDMS程序不用等待调用的程序是否执行完毕呢?PDMS中也提供了方法,那就是在程序名后加个
&
。如
syscom ‘calc&’
,就可以打开计算器程序而不用去等待是否将其关闭。
有了这条命令,把PDMS的扩展性又提高了,因为可以用syscom来调用Windows中的脚本即批处理文件。这样就可以用批处理来调用其他程序,由此摆脱因为AVEVA .NET(C#)开发时加载DLL后调试的不便,也可摆脱编程语言的限制,只要是一个程序都可以通过批处理来调用,即可以用C/C++或C#甚至VB来编写程序,再用通过syscom来调用。