Eplan API Add-ins
一、使用 C# 创建插件
- 本节介绍了如何使用 C# 创建 EPLAN 插件。为了表明已安装的 .NET 框架已经提供了所有必要的工具(如 C# 编译器等),该插件并非以 Visual Studio 项目的形式创建,而是仅通过文本编辑器和 .NET 框架的命令行工具来实现。
1、开始步骤:
- 首先,创建一个目录来存放您的插件的源代码是很有用的。在这个示例中,我们创建了一个名为“SimpleCSharpAddIn”的文件夹。
- 现在,请使用您喜欢的文本编辑器(例如记事本)开始编写源代码。
2、创建模块类:
- 每一个 EPLAN 插件(包括我们将要创建的 C# 插件)都需要一个用于管理插件的特定类。该类必须实现由 IEplAddIn 接口所声明的功能:
/// <summary>
/// EPLAN插件模块基类实现
/// 负责处理插件的注册、初始化、GUI加载和退出等生命周期事件
/// </summary>
public class AddInModule : Eplan.EplApi.ApplicationFramework.IEplAddIn
{/// <summary>/// 插件注册时调用的方法/// </summary>/// <param name="bLoadOnStart">是否在EPLAN启动时自动加载</param>/// <returns>注册成功返回true,失败返回false</returns>public bool OnRegister(ref System.Boolean bLoadOnStart){// 设置插件在EPLAN启动时自动加载bLoadOnStart = true;// 可在此添加自定义注册逻辑,如初始化配置Logger.Info("插件已成功注册,将在EPLAN启动时自动加载");return true; // 返回true表示注册成功}/// <summary>/// 插件卸载时调用的方法/// </summary>/// <returns>卸载成功返回true,失败返回false</returns>public bool OnUnregister(){// 可在此添加资源释放逻辑,如关闭文件、断开连接等Logger.Info("插件已成功卸载");return true; // 返回true表示卸载成功}/// <summary>/// EPLAN初始化时调用的方法(早于GUI加载)/// </summary>/// <returns>初始化成功返回true,失败返回false</returns>public bool OnInit(){// 执行核心组件初始化,如加载配置文件、初始化数据库连接等Logger.Info("插件核心组件初始化完成");return true; // 返回true表示初始化成功}/// <summary>/// EPLAN GUI初始化完成后调用的方法/// </summary>/// <returns>GUI初始化成功返回true,失败返回false</returns>public bool OnInitGui(){// 执行与GUI相关的初始化,如添加菜单项、注册工具栏等RegisterRibbonItems(); // 示例方法:注册Ribbon元素Logger.Info("插件GUI组件初始化完成");return true; // 返回true表示GUI初始化成功}/// <summary>/// EPLAN退出时调用的方法/// </summary>/// <returns>退出处理成功返回true,失败返回false</returns>public bool OnExit(){// 执行资源释放操作,如保存配置、关闭连接等SaveSettings(); // 示例方法:保存插件设置Logger.Info("插件已完成退出处理");return true; // 返回true表示退出处理成功}// 示例方法:注册Ribbon元素private void RegisterRibbonItems(){// 实现Ribbon界面元素注册逻辑// 例如:添加选项卡、命令组和命令按钮}// 示例方法:保存插件设置private void SaveSettings(){// 实现插件设置保存逻辑// 例如:将配置写入XML文件或注册表}
}
- 现在将这段源代码保存到“SimpleCSharpAddIn”文件夹中,以“AddInModule.cs”为文件名保存。
3、编译程序集(DLL)
-
现在是时候使用 C# 编译器了。该编译器位于.NET 框架的目录中,例如 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727。此文件夹应包含在搜索路径中。打开您喜欢的终端窗口,并切换到刚刚保存“AddInModul.cs”的“SimpleCSharpAddInwhere”目录。
-
使用以下参数运行 C# 编译器(csc.exe):
csc /target:library /reference:…\bin\Eplan.EplApi.AFu.dll /out: EPLAN.EplAddin.SimpleCSharp.dll AddinModule.cs -
这些参数的含义是什么?
- /taget:library: 我们想要创建一个动态链接库(DLL),而不是可执行文件(exe)。
- /reference:…\bin\Eplan.EplApi.AFu.dll: 在 Eplan.EplApi.AFu.dll 中查找所有缺失的数据(例如 IEplAddIn)
- /out: EPLAN.EplAddin.SimpleCSharp.dll: 要构建的 DLL 的名称为“EPLAN.EplAddin.SimpleCSharp.dll”
- AddinModul.cs: 需要编译的源文件名称
-
如果编译过程中没有出现任何问题,那么您现在会在“SimpleCSharpAddIn”文件夹中找到名为“EPLAN.EplAddin.SimpleCSharp.dll”的动态链接库文件。请将此文件复制到 EPLAN 平台的“bin”文件夹中。
4、在 EPLAN 中加载插件
- 现在启动 EPLAN。如果在 EPLAN 中已加载以下系统扩展(通常情况下应该是这样):EplanEplApiModuleu.erx,EplanEplApiModuleGUIu.erx。
点击功能区“文件”>“附加功能”>“接口”>“API”>“管理”。

- 点击“管理”后,将会出现如下的对话框。然后点击“加载”按钮,您可以在“bin”目录中选择“Eplan.EplAddin.SimpleCSharp.dll”文件。

- 我们的插件现已出现在“API 模块”对话框的列表中,并会在 EPLAN 启动时自动加载。这就是它所能完成的全部工作了。现在我们需要的是一个操作!
5、向 C# 插件中添加操作
- 因此,创建一个第二个源文件,并将其保存在您的源目录中,命名为“SimpleCSharpAction.cs”。要创建一个操作,我们需要一个实现了 IEplAction 接口的类。如需更详细的说明,请参阅“操作”主题。
using Eplan.EplApi.ApplicationFramework;
public class CSharpAction: IEplAction
{public bool Execute(ActionCallingContext ctx ){new Decider().Decide(EnumDecisionType.eOkDecision, "CSharpAction was called!", "", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK);return true;}public bool OnRegister(ref string Name, ref int Ordinal){Name = "CSharpAction";Ordinal = 20;return true;}public void GetActionProperties(ref ActionProperties actionProperties){actionProperties.Description= "Action test with parameters.";}
}
- 现在,编译器调用的范围需要稍作扩展:
csc /target:library /reference:…\bin\Eplan.EplApi.AFu.dll /reference:…\bin\Eplan.EplApi.Baseu.dll /out:SimpleCSharpAddIn.dll AddinModule.cs SimpleCSharpAction.cs
- 如果您在已加载的插件中添加了某个操作,那么需要先卸载该插件,然后再重新加载,这样更改才能生效。
- 所以您只需再次打开“API 模块”对话框,从列表中选择该插件,然后点击“卸载”按钮。接着再重新加载该插件即可。
- 现在,您可以通过命令行调用的方式在 EPLAN 中执行您的新操作:W3u.exe CSharpAction
- 当您启动该操作时,CSharpAction 类的 Execute() 函数会被调用。此函数会显示一个带有文本“CSharpAction 已被调用!”的消息框。
(new Decider().Decide(EnumDecisionType.eOkDecision, “CSharpAction was called!”, “”, EnumDecisionReturn.eOK, EnumDecisionReturn.eOK); ).
备注
- 请注意,用户可以通过使用“W3u.exe /Quiet”命令以安静模式启动 EPLAN,或者也可以通过离线程序来初始化 API。鉴于此,不建议在 IEplAddIn 接口的方法中显示任何消息框。如果您在注册或初始化插件时遇到问题,只需创建并抛出一个 BaseException 或使用 BaseException.FixMessage(…) 来将消息添加到系统消息列表中。
二、在 Visual Basic.Net 中创建插件
- 使用 Visual Basic.NET 编写插件的过程与“使用 C# 创建插件”这一主题中所描述的基本上是相同的。唯一的区别在于源代码的语法以及调用编译器的方式。
- 创建一个名为“VBAddInModule.vb”的文件,并在其中输入以下内容:
Public Class AddInModuleImplements Eplan.EplApi.ApplicationFramework.IEplAddInPublic Function OnRegister(ByRef bLoadOnStart As System.Boolean) As Boolean _Implements Eplan.EplApi.ApplicationFramework.IEplAddIn.OnRegisterbLoadOnStart = TrueReturn TrueEnd Function 'OnRegisterPublic Function OnUnregister() As Boolean _Implements Eplan.EplApi.ApplicationFramework.IEplAddIn.OnUnregisterReturn TrueEnd Function 'OnUnregisterPublic Function OnInit() As Boolean _Implements Eplan.EplApi.ApplicationFramework.IEplAddIn.OnInitReturn TrueEnd Function 'OnInitPublic Function OnInitGui() As Boolean _Implements Eplan.EplApi.ApplicationFramework.IEplAddIn.OnInitGuiReturn TrueEnd Function 'OnInitGuiPublic Function OnExit() As Boolean _Implements Eplan.EplApi.ApplicationFramework.IEplAddIn.OnExitReturn TrueEnd Function 'OnExit
End Class 'AddInModule
- 使用以下参数调用 Visual Basic 编译器(vbc.exe):
vbc /target:library /reference:…\bin\Eplan.EplApi.AFu.dll /out:SimpleVBAddIn.dll VBAddinModule.vb
- 要创建一个操作,请创建以下源文件,并将其保存在您的源目录中,命名为“SimpleVBAction.cs”。要创建一个操作,我们需要一个实现了 IEplAction 接口的类。如需更详细的说明,请参阅“操作”主题。
Imports Eplan.EplApi.ApplicationFrameworkPublic Class VBActionImplements IEplActionPublic Function Execute(ctx As ActionCallingContext) As Boolean Implements IEplAction.ExecuteDim dec As Decider = New Deciderdec.Decide(EnumDecisionType.eOkDecision, "VBAction was called!", "", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK)Return TrueEnd Function 'ExecutePublic Function OnRegister(ByRef Name As String, ByRef Ordinal As Integer) As Boolean _Implements IEplAction.OnRegisterName = "VBAction"Ordinal = 20Return TrueEnd Function 'OnRegisterPublic Sub GetActionProperties(ByRef actionProperties As ActionProperties) _Implements IEplAction.GetActionPropertiesactionProperties.Description = "Action test with parameters."End Sub 'GetActionProperties
End Class 'VBAction
vbc /target:library /reference:…\bin\Eplan.EplApi.AFu.dll /reference:…\bin\Eplan.EplApi.Baseu.dll /out:SimpleVBAddIn.dll VBAddinModule.vb SimpleVBAction.vb
三、在 Visual Studio 中创建插件
- 与使用.NET Framework 提供的文本编辑器和编译器相比,使用像 Visual Studio 2022 这样的开发环境来创建插件要容易得多。
- Eplan 模板是通过 API 安装程序安装在 Visual Studio 中的,该安装程序可以从 EPLAN 官方网站下载。
- 要创建一个插件,只需在 Visual Studio 中使用“Eplan Api Addin”模板(来自 C# 项目)创建一个项目即可。

- 这个新项目已经引用了基本的 EPLAN API 组件以及一个包含模块类的文件:

- 您可以通过“添加新项目”菜单选项来添加一个新的“操作”类,并选择“Eplan 操作”模板即可:

- 对于 Visual Basic 而言,其工作流程是完全相同的。
四、复制 API 程序集
- 自 2.6 版本起,EPLAN API 组件采用影子复制方式,即在注册过程中它们会被保存在临时文件夹中,并从该文件夹中加载。
- 影子复制技术的优点在于,原始程序集并未被锁定,因此即使当前有其他工作站正在使用这些版本,新的版本仍可以通过网络共享进行分发。
- 这既适用于附加组件,也适用于插件。
1、Add-ons
- 该附加组件的整个“bin”目录及其子目录都会被复制到用户应用程序的 roaming 目录(%appdata%\EPLAN\ShadowCopyAssemblies\Process-ID\Addon-Name)中。
- 这意味着所有文件(*.dll 和 *.exe)以及所有“bin”子目录(语言子目录等)也会被一并复制。这一操作会在 EPLAN 启动时以及注册插件或从“插件”对话框手动注册插件时进行。
- EPLAN 会从辅助目录中加载附加组件的组件文件,而非从原始的附加组件目录中加载。这样一来,即使要更新附加组件,也无需停止所有使用该附加组件的 EPLAN 实例。
2、Add-ins
- 当插件通过 EPLAN 的启动方式或通过 API 的“管理”选项加载时,它会被复制到一个临时目录中(%appdata%\EPLAN\ShadowCopyAssemblies\Process-ID\)内。
- EPLAN 会保留原始的插件路径,以便后续进行组件的解析工作。这意味着,如果一个插件引用了来自该插件原始路径的其他组件,那么这些被引用的组件将会被找到。
- 在解决之后,这些内容将会被复制到影子目录中。问题可能在于使用相对于原始插件目录的相对路径来引用其他目录中的数据。
- 为此,我们创建了 IEplAddInShadowCopy 接口,该接口能够获取插件的原始路径。
- 此外,当解决方案中的多个插件/附加组件项目引用具有相同名称但不同版本的具有命名空间和类的程序集时,可能会出现冲突。以下场景应予以考虑:例如,如果在一个项目(Project1)中使用版本为 1.0.0 的“Write”库,而在另一个项目(Project2)中使用版本为 2.0.0 的“Write”库,这将导致您的解决方案出现不期望的行为。
- 取决于您首先调用的是哪个项目——无论是项目 1 还是项目 2——该项目都会被正确执行,并会引用正确的库。然后如果再执行另一个项目,它将引用之前的库,即先执行的那个版本的库。
- 为解决这种问题,应分别独立地对库版本进行签名。这样您就可以随意使用不同版本的库了。
- 签名会为库生成一个特定的密钥令牌或“强名称”,这有助于区分不同的库。
五、呼叫操作
- 在 P8 中,所有的功能区按钮都与一个操作相关联。这意味着当调用功能区按钮时,相应的操作就会被执行。要通过 EPLAN API 执行一个操作,您需要创建一个“操作”对象,并使用“执行”方法来执行该操作。
- 要创建一个“动作”对象,您需要根据其名称来确定该动作。您需要创建一个新的“动作管理器”对象,并调用“查找动作”函数,该函数会将动作的名称作为参数进行调用。
- 要传递和评估操作参数,您需要使用“ActionCallingContext”类:
String strAction = "TestAction";
ActionManager oAMnr= new ActionManager();
Action oAction= oAMnr.FindAction(strAction);
if (oAction != null)
{ActionCallingContext ctx = new ActionCallingContext();bool bRet=oAction.Execute(ctx);if (bRet){ new Decider().Decide(EnumDecisionType.eOkDecision, "The Action " + strAction + " ended successfully!", "", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK);}else{new Decider().Decide(EnumDecisionType.eOkDecision, "The Action " + strAction + " ended with errors!", "", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK);}
}
- 要确定哪个操作与哪个功能区按钮相关联,您可以查看“onActionStart.String.*”事件。或者,在点击功能区按钮后,按 [Ctrl] + [VK_OEM_5] 可以显示诊断对话框。[VK_OEM_5] 对应于德式键盘上的【^】键或美式 101 键盘上的 【\】 键。
重要提示:
- 请注意,一个操作在执行过程中可能会修改“ActionCallingContext”。例如,有时项目 ID 会被添加到该上下文中,并传递给内部操作。如果在对另一个操作调用时重复使用同一个“ActionCallingContext”,可能会导致意想不到的结果。因此,在大多数情况下,建议为新的操作调用创建一个新的“ActionCallingContext”。
命令行调用
- 若要通过添加新命令和参数来扩展 EPLAN 命令行,您需要实现一个操作。该操作可以有自己的参数,并且能够调用其他 API 函数。
- 这样一来,在启动 EPLAN 后就会立即执行一项操作,例如:
EPLAN.EXE /Variant:“Electric P8” /NoLoadWorkspace action /Param1:value1 /Param2:value2 /Param3:value3
- 没有标志符(/ 或 -)的参数将被解释为要执行的操作的名称。所有后续的参数都将传递给该操作。每次命令行调用中只允许执行一个操作。
- 一个脚本还可以包含并注册一个操作。这意味着它还能对操作参数进行评估。
- 在动作名称之前,有必要先传递一些更通用的命令行参数。
- EPLAN 所评估的通用命令行参数列表:
| Parameter | Description |
|---|---|
| /Variant | 选择要启动的产品变体。例如:“Electric P8” 或 “Fluid” |
| /NoLoadWorkspace | 不加载或恢复工作区。 |
| /NoSplash | 系统启动时不显示 splash 屏幕(启动画面)。 |
| /Language:en_us | EPLAN 启动时使用 GUI 语言“英语”。EPLAN 设置中预定义的语言不会被更改。 |
| /Auto | 执行命令行后 EPLAN 自动关闭。 |
| /Quiet | 执行命令行时不显示任何对话框。 |
| /Frame:0 | EPLAN 主窗口不可见 |
| /Frame:1 | EPLAN 主窗口恢复到原始大小和位置 |
| /Frame:2 | EPLAN 主窗口以最小化方式启动 |
| /Frame:3 | EPLAN 主窗口以最大化方式启动 |
| /Setup | 所有设置恢复为安装默认值。 |
| <action name> | 要执行的操作,后续所有以 / 或 – 开头的参数将作为该操作的参数传递。 |
- 在动作名称之后的任何命令行参数都会作为参数传递给该动作。这些参数会被封装为字符串参数并放入一个名为“ActionCallingContext”的对象中,动作可以从中提取这些参数。请注意,命令行中的参数名称和“ActionCallingContext”中的参数名称必须完全一致:
EPLAN.EXE /Variant:“Electric P8” action /Param1:value1 /Param2:value2 /Param3:value3
public bool Execute(ActionCallingContext ctx )
{String strParamValue1=null;ctx.GetParameter("Param1", ref strParamValue1);String strParamValue2=null;ctx.GetParameter("Param2", ref strParamValue2);String strParamValue3=null;ctx.GetParameter("Param3", ref strParamValue3);return true;
}
- 警告:若从命令行以操作方式启动 EPLAN,则在会话开始时不会自动打开之前已打开的项目。
五、自动操作
- 本主题介绍 EPLAN 命令行的自动操作 —— 我们也称之为 “命令行操作”。与普通的功能区操作不同,自动操作无需用户交互即可完成整个任务,不会显示任何对话框。
1、自动操作的工作原理
- 命令行操作首先会检查传递给它的所有参数是否有效。它会检查给定的参数是否存在、指定的项目是否可用等。然后,它会处理参数值,以便将这些值传递给相应的 API(HEServices 类)的参数。接着,HEServices 函数会被调用并执行实际任务。这种方式确保了命令行操作和 HEServices 函数执行完全相同的内部功能。
- 一个命令行操作拥有相应 HEServices 类的全部功能或部分功能。其原理如下图所示:

以下是一些可用的命令行操作:
Backup projects and master data
Restore projects and master data
Compress projects
Import
Export
Device list
Parts list
Connections and cable generation
Search
Edit
Translate
Check
Labeling
Getting the selected project or page
2、一般说明
- 如果未指定项目名称参数,则将使用当前选定的项目。在通过 Windows 命令行调用此操作时,必须设置“PROJECTNAME”参数。
- 布尔值需要设置为“0”表示“false”,设置为“1”表示“true”。
您不能将空字符串作为参数值传递(例如,/PARAMETER:“”)。如果您不想设置特定参数,只需跳过它。 - 对于大多数指定方案名称的参数,如果未设置相应的参数,则将使用最后使用的方案。您可以在图形用户界面中轻松查看最后使用的方案是哪一个。
- 一般来说,参数名称不区分大小写,而参数值可能根据其用途而区分大小写。
六、添加书签命令
- 一个插件可以向“扩展 > API”命令组中添加一个或多个功能区命令。因此,类“Eplan.EplApi.Gui.RibbonBar”提供了“AddCommand”函数,该函数应在插件类的“OnRegister()”方法中调用:
/// <summary>
/// The function is called once during registration add-in.
/// </summary>
/// <param name="bLoadOnStart"> true: In the next Eplan session, add-in will be loaded during initialization</param>
/// <returns></returns>
public bool OnRegister(ref System.Boolean bLoadOnStart)
{var ribbonBar= new Eplan.EplApi.Gui.RibbonBar();ribbonBar.AddCommand("CSharpAction", "CSharpAction");return true;
}/// <summary>
/// The function is called during unregistration the add-in.
/// </summary>
/// <returns></returns>
public bool OnUnregister()
{var ribbonBar = new Eplan.EplApi.Gui.RibbonBar();return ribbonBar.RemoveCommand("CSharpAction");
}
- 函数“AddCommand(text, command line)”会添加一个带有文本“CSharpAction”的按钮(即功能区命令),并将操作“CSharpAction”赋予该按钮。该按钮随后会在“扩展” > “API 命令组”中可见。还可以将其添加到存在于持久化或自定义标签页中的自定义命令组中。
- Ribbon 命令总是与某个操作相关联。该操作既可以是自定义操作(通过 API 创建),也可以是已有的操作。