EPLAN

EPLAN API: Seitenmakros einfügen

Ich generiere gerade bisschen mit der API um ein Gefühl zu bekommen was alles möglich ist. Leider ist es nicht ganz trivial Seitenmakros einzufügen.

Problem: Äquivalent zur EPLAN GUI wird das Makro einfach eingefügt. Seiten werden überschrieben, oder auch nicht.

Als Workaround kann man die Seiten im Makro in der API davor anpassen und trotzdem die Strukturkennzeichen beibehalten.
Im Beispiel zähle ich einfach die Seiten vom Projekt hoch (Basisprojekt muss somit durchnummeriert sein).

Insert insert = new Insert();
var pageCount = project.Pages.Length; // needed cause of overwrite
foreach (var pageMacroFile in pageMacros)
{
	// Load pages from macro
	PageMacro pageMacro = new PageMacro();
	pageMacro.Open(pageMacroFile, project);
	foreach (var page in pageMacro.Pages)
	{
		// Rename
		pageCount++;
		PagePropertyList pagePropertyList = page.NameParts;
		pagePropertyList[Properties.Page.DESIGNATION_PLANT] = "TEST";
		pagePropertyList[Properties.Page.PAGE_COUNTER] = pageCount;
		page.NameParts = pagePropertyList;
		new NameService(page).EvaluateAndSetAllNames();
	}

	// Insert pagemacro
	insert.PageMacro(pageMacro, project, null, PageMacro.Enums.NumerationMode.Number);
}

Das hin und her bei Rename muss leider sein, da es nicht möglich ist direkt auf die Properties des Objektes zu gehen.

NameService.EvaluateAndSetAllNames()  nummeriert die Betriebsmittel auf der Seite.

Ich bau mal was zusammen damit man die Strukturkennzeichen schön von außen mit übergeben kann :^)
Ist wie gewohnt auf GitHub zu finden.

Von |2017-11-09T11:23:42+01:002016-02-10|EPLAN, EPLAN-API|

EPLAN API: Preview in WPF

Da es nicht ganz so einfach ist in WPF eine Vorschau im Offline Programm zu implementieren, habe ich das mal in eine Klasse gepackt.

Mir ist aufgefallen dass der Speicher hochläuft und habe hier auf EPLAN getippt… Nach Rücksprache mit dem API-Support wurde mir gesagt dass es nicht der Speicher von EPLAN ist, sondern der Applikation, bzw. WPF.

Speicher

Ich habe hier mal die Generierung der Bitmap in Verdacht gezogen und siehe da, bekannter Bug.
Hier mal im Vergleich:

Speicher2

Auf GitHub findet ihr auch eine Demo-Applikation dazu.

Preview

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Eplan.EplApi.DataModel;
using System.Runtime.InteropServices;
using Eplan.EplApi.DataModel.MasterData;
using Eplan.EplApi.HEServices;

namespace Suplanus.Sepla.Gui
{
	public class Preview
	{
		private readonly Border _border;
		private readonly DrawingService _drawingService;
		private readonly Project _project;

		/// <summary>
		/// Init Preview object for WPF
		/// </summary>
		/// <param name="border"></param>
		/// <param name="projectFile"></param>
		public Preview(Border border, string projectFile)
		{
			var projectManager = new ProjectManager();
			projectManager.LockProjectByDefault = false;
			_project = projectManager.OpenProject(projectFile, ProjectManager.OpenMode.Exclusive);

			_drawingService = new DrawingService();
			_drawingService.DrawConnections = true;

			_border = border;
		}

		/// <summary>
		/// Display a file
		/// </summary>
		/// <param name="path">Full filename</param>
		/// <param name="previewType">Type of file</param>
		public void Display(string path, PreviewType previewType)
		{
			switch (previewType)
			{
				case PreviewType.WindowMacro:
					WindowMacro windowMacro = new WindowMacro();
					windowMacro.Open(path, _project);
					_drawingService.CreateDisplayList(windowMacro);
					DrawEplan();
					windowMacro.Dispose();
					break;

				case PreviewType.SymbolMacro:
					SymbolMacro symbolMacro = new SymbolMacro();
					symbolMacro.Open(path, _project);
					_drawingService.CreateDisplayList(symbolMacro);
					DrawEplan();
					symbolMacro.Dispose();
					break;

				case PreviewType.PageMacro:
					PageMacro pageMacro = new PageMacro();
					pageMacro.Open(path, _project);
					_drawingService.CreateDisplayList(pageMacro.Pages);
					DrawEplan();
					pageMacro.Dispose();
					break;

				default:
					throw new ArgumentOutOfRangeException(nameof(previewType), previewType, null);
			}

		}

		/// <summary>
		/// Draw EPLAN files
		/// </summary>
		private void DrawEplan()
		{
			int width = Convert.ToInt16(_border.ActualWidth);
			int height = Convert.ToInt16(_border.ActualHeight);

			if (width > 0 && height > 0)
			{
				System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height);
				System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap);
				System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(0, 0, width, height);
				PaintEventArgs paintEventArgs = new PaintEventArgs(graphics, rectangle);

				_drawingService.DrawDisplayList(paintEventArgs);

				IntPtr hBitmap = bitmap.GetHbitmap();
				BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap,
					IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

				_border.Background = new ImageBrush(bitmapSource);

				bitmap.Dispose();
				graphics.Dispose();
				paintEventArgs.Dispose();
				DeleteObject(hBitmap);
			}
			else
			{
				_border.Background = null;
			}

		}

		/// <summary>
		/// Memory Leak: http://stackoverflow.com/questions/1546091/wpf-createbitmapsourcefromhbitmap-memory-leak
		/// </summary>
		/// <param name="hObject"></param>
		/// <returns></returns>
		[DllImport("gdi32.dll")]
		public static extern bool DeleteObject(IntPtr hObject);
	}

	
	/// <summary>
	/// Filetype to preview
	/// </summary>
	public enum PreviewType
	{
		WindowMacro,
		SymbolMacro,
		PageMacro
	}
}
Von |2017-11-09T11:23:52+01:002016-02-03|EPLAN, EPLAN-API|

EPLAN RemoteClient

Ich hatte ja schon erklärt wie man EPLAN per COM-Schnittstelle ansprechen kann.

Nachteil: Bei 32/64bit gewinnt der Server der als erstes gestartet wurde.
Aber es gibt einen Weg mit dem man sogar die Version auswählen kann (wenn z.B. mehrere EPLAN Versionen installiert bzw. geöffnet sind).

Diese Schnittstelle ist nicht offiziell dokumentiert!

 

Ihr müsst eine Referenz auf die DLL Eplan.EplApi.RemoteClientu.dll machen, welche sich im Installationsverzeichnis von EPLAN befindet, z.B.:

C:\Program Files\EPLAN\Platform\2.5.4\Bin\

 

Hier ein Beispiel wie man die aktuellen EPLAN Versionen erhält und bei der aktuellsten das Projekt schließt:

EplanRemoteClient eplanRemoteClient = new EplanRemoteClient();
List eplanServerDatas = new List();
eplanRemoteClient.GetActiveEplanServersOnLocalMachine(out eplanServerDatas);
if (eplanServerDatas.Count > 0)
{
	var eplanServerDataLast = eplanServerDatas.OrderBy(obj=>obj.EplanVersion).LastOrDefault();
	if (eplanServerDataLast != null)
	{
		eplanRemoteClient.Connect("localhost", eplanServerDataLast.ServerPort.ToString(),new TimeSpan(0,0,0,5));
		eplanRemoteClient.ExecuteAction("XPrjActionProjectClose");
		eplanRemoteClient.Disconnect();
	}
}

Localhost für den lokalen Rechner verwenden, den Timespan brauchte ich, da EPLAN zu langsam reagierte.

Von |2017-11-09T11:22:15+01:002016-01-29|EPLAN, EPLAN-Scripts|

EPLAN-API: Offline Applikation starten

Mit der Offline Applikation hat man man vielen Problemen zu kämpfen, angefangen beim Start…

Ich hab auf GitHub mal Methoden bereitgestellt um das zu vereinfach.

 

Verwendung WPF

var eplanOffline = new EplanOffline();
eplanOffline.StartWpf(this);
if (!eplanOffline.IsRunning)
{
	throw new NotImplementedException();
}
eplanOffline.Close();

Verwendung Windows Forms

var eplanOffline = new EplanOffline();
eplanOffline.StartWindowsForms(this);
if (!eplanOffline.IsRunning)
{
	throw new NotImplementedException();
}
eplanOffline.Close();

 

Ich habe bewusst darauf verzichtet dass alles im Konstruktor zu machen, da sonst WindowsForms in WPF und anders herum hinzugefügt werden muss.

Hier mal der Code dazu (Starter ist zum registrieren der Lizenz/DLLs):

using System.Collections.Generic;
using System.IO;
using System.Linq;
using Eplan.EplApi.Starter;

namespace Suplanus.Sepla.Application
{
    /// <summary>
    /// EPLAN Starter Helper: No other EPLAN-Namespaces are allowd
    /// </summary>
    public class Starter
    {
        public static string GetBinPathLastVersion()
        {
            List<EplanData> eplanVersions = new List<EplanData>();

            List<EplanData> eplanVersions32Bit = new List<EplanData>();
            new EplanFinder().GetInstalledEplanVersions(ref eplanVersions32Bit);
            eplanVersions.AddRange(eplanVersions32Bit);

            List<EplanData> eplanVersions64Bit = new List<EplanData>();
            new EplanFinder().GetInstalledEplanVersions(ref eplanVersions64Bit, true);
            eplanVersions.AddRange(eplanVersions64Bit);

            eplanVersions = new List<EplanData>(eplanVersions
                .Where(obj => obj.EplanVariant.Equals("Electric P8"))
                .OrderBy(obj => obj.EplanVersion));

            EplanData eplanData = eplanVersions.LastOrDefault();

            var binPath = Path.GetDirectoryName(eplanData.EplanPath);

            AssemblyResolver resolver = new AssemblyResolver();
            resolver.SetEplanBinPath(binPath);
            resolver.PinToEplan();

            return binPath;
        }
    }
}

 

using System;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
using Eplan.EplApi.System;
using Suplanus.Sepla.Gui;

namespace Suplanus.Sepla.Application
{
    public class EplanOffline
    {
        public EplApplication Application;

	    public Preview Preview;

		/// <summary>
		/// Starts EPLAN with the last version of Electric P8 and attach to (WPF) window
		/// </summary>
		/// <param name="window"></param>
		public void StartWpf(Window window)
	    {
			IntPtr handle = new WindowInteropHelper(window).Handle;
			string binPath = Starter.GetBinPathLastVersion();
			Start(handle,binPath);
		}

		/// <summary>
		/// Starts EPLAN with the last version of Electric P8 and attach to (WF) form
		/// </summary>
		/// <param name="form"></param>
		public void StartWindowsForms(Form form)
		{
			IntPtr handle = form.Handle;
			string binPath = Starter.GetBinPathLastVersion();
			Start(handle, binPath);
		}

		/// <summary>
		/// Starts EPLAN with the given version of program variant and attach to (WPF) window
		/// </summary>
		/// <param name="window"></param>
		/// <param name="binPath"></param>
		public void StartWpf(Window window, string binPath)
		{
			IntPtr handle = new WindowInteropHelper(window).Handle;
			Start(handle, binPath);
		}

		/// <summary>
		/// Returns if the EPLAN-Application is running
		/// </summary>
		public bool IsRunning
        {
            get { return Application != null; }
        }

	    

	    /// <summary>
		/// Starts the application
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="binPath"></param>
        private void Start(IntPtr handle, string binPath)
        {
            if (Application == null)
            {
                try
                {
                    EplApplication eplApplication = new EplApplication();
                    eplApplication.EplanBinFolder = binPath;
                    eplApplication.ResetQuietMode();
                    eplApplication.SetMainFrame(handle);
                    eplApplication.Init("", true, true);
                    Application = eplApplication;
                }
                catch
                {
                    Application = null;
                } 
            }
        }

		/// <summary>
		/// Release all objects
		/// </summary>
        public void Close()
        {
            if (Application != null)
            {
                Application.Exit();
                Application = null;
            }
        }
    }
}

In diesem Code wird immer die aktuellste Version von EPLAN Electric P8 verwendet. Ich bau irgendwann noch Methoden zur Auswahl von der Lizenz / Version.

Von |2017-11-09T11:23:59+01:002016-01-28|EPLAN, EPLAN-API|

GetProjectVariableLanguage

Ich hatte mal schon geschrieben wie man die Projekt-Sprachen rausfindet

Hier noch ein Script wie man die variable Sprache herausfindet.
Einfach das Script laden und in einem anderen Script das Usage ausführen.

 

using System.IO;
using System.Xml;
using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.Base;
using Eplan.EplApi.Scripting;

class GetProjectVariableLanguage
{
	/* Usage
	private static string GetProjectVariableLanguage()
	{
		string value = null;
		ActionCallingContext actionCallingContext = new ActionCallingContext();
		new CommandLineInterpreter().Execute("GetProjectVariableLanguage", actionCallingContext);
		actionCallingContext.GetParameter("value", ref value);
		return value;
	}
	*/

	private readonly string TempPath = Path.Combine(
		PathMap.SubstitutePath("$(TMP)"), "GetProjectLanguages.xml");

	[DeclareAction("GetProjectVariableLanguage")]
	public void Action(out string value)
	{
		ActionCallingContext actionCallingContext = new ActionCallingContext();
		actionCallingContext.AddParameter("prj", FullProjectPath());
		actionCallingContext.AddParameter("node", "TRANSLATEGUI");
		actionCallingContext.AddParameter("XMLFile", TempPath);
		new CommandLineInterpreter().Execute("XSettingsExport", actionCallingContext);

		if (File.Exists(TempPath))
		{
			string languagesString = GetValueSettingsXml(TempPath,
				"/Settings/CAT/MOD/Setting[@name='VAR_LANGUAGE']/Val");

			if (languagesString != null)
			{
				value = languagesString;
				return;
			}
		}

		value = null;
		return;
	}

	// Returns the EPLAN Project Path
	private static string FullProjectPath()
	{
		ActionCallingContext acc = new ActionCallingContext();
		acc.AddParameter("TYPE", "PROJECT");

		string projectPath = string.Empty;
		new CommandLineInterpreter().Execute("selectionset", acc);
		acc.GetParameter("PROJECT", ref projectPath);

		return projectPath;
	}

	// Read EPLAN XML-ProjectInfo and returns the value
	private static string GetValueSettingsXml(string filename, string url)
	{
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.Load(filename);

		XmlNodeList rankListSchemaName = xmlDocument.SelectNodes(url);
		if (rankListSchemaName != null && rankListSchemaName.Count > 0)
		{
			// Get Text from MultiLanguage or not :)
			string value = rankListSchemaName[0].InnerText;
			return value;
		}
		else
		{
			return null;
		}
	}
}
Von |2017-11-09T11:22:16+01:002016-01-11|EPLAN, EPLAN-Scripts|
Nach oben