Skript

Script Debugging: Debugger.IsAttached

Ich hatte hier mal beschrieben wie man den Debugger automatisch anhält… Leider zeigt EPLAN einen Fehler wenn kein Visual Studio dran hängt.
Es geht wie immer besser… Nutzt das hier, dann hält Visual Studio nur an wenn die Einstellung für das Debugging aktiv ist und Visual Studio an EPLAN.exe hängt:

if (Debugger.IsAttached)
{
  Debugger.Break(); 
}

Das kann man sich auch schön verpacken und wie folgt nutzen:

using System.Diagnostics;
using System.Windows.Forms;
using Eplan.EplApi.Scripting;
using Action = System.Action;

public class Test
{
  [Start]
  public void Function()
  {
    Debug(Debugger.Break);

    Debug(()=> MessageBox.Show("Hallo"));

    Debug(() =>
    {
      MessageBox.Show("Hallo");
    });
  }

  private void Debug(Action action)
  {
    if (Debugger.IsAttached)
    {
      action.Invoke();
    }
  }
}

Der Debugger wird nur angehalten wenn Visual Studio dran hängt. Auch die MessageBoxen werden nur angezeigt wenn das der Fall ist. Man kann mit der dritten Varianten auch mehrere Zeilen Code ausführen. Ist zwar nur syntaktischer Zucker, aber denke wird bei mir Anwendung finden.

Von |2018-01-26T15:08:40+01:002018-01-26|EPLAN, EPLAN-Scripts|

LockingVector

Jeder der in der EPLAN API programmiert, kennt die Aufwände beim Locking. Es ist mir nicht immer ganz klar wann was zu verwenden ist. LockingVector sollte nur in Ausnahmefällen verwendet werden, es kann zu unschönen Verhalten kommen. Auch so in der API-Hilfe beschrieben.

Der LockingVector hebelt das Locking komplett aus und die API verhält sich ähnlich wie die Oberfläche. Hört sich gut an, aber wie gesagt für mich nur mit Vorsicht zu genießen.

Dennoch gibt es für mich einen Anwendungsfall: Interne EPLAN Action im API ausführen… Ja manchmal muss man das. Hatte mit Auswertungen aktualisieren den Fall:

LockingVector lockingVector = new LockingVector();
int manualLockStateId = lockingVector.PauseManualLock();

new CommandLineInterpreter().Execute("XFgUpdateEvaluationAction");

lockingVector.ResumeManualLock(manualLockStateId);

Wichtig ist dass ResumeManualLock()  nicht vergessen wird… Ich hab mir das mal in ein Using gepackt, das sich um alles kümmert und auch die Klasse auf GitHub bereitgestellt:

using (new LockingUtility.SeplaLockingVector())
{
  new CommandLineInterpreter().Execute("XFgUpdateEvaluationAction");
}
Von |2018-01-26T14:43:53+01:002018-01-24|EPLAN, EPLAN-API|

Script Debugging: Attach to Process

Für das Script-Debuggen muss man sich ja an den EPLAN Prozess hängen… Das kann man auch recht schön automatisieren.

Hier der Code für das Makro:

using EnvDTE;
using EnvDTE80;
using System.Management;
using System;

public class C : VisualCommanderExt.ICommand
{
    public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) 
    {
        foreach(Process proc in DTE.Debugger.LocalProcesses)
        {
            if(proc.Name.ToString().EndsWith("EPLAN.exe"))
            {
                proc.Attach();
                return;
            }
        }

        System.Windows.MessageBox.Show("Process running the EPLAN was not found.");
    }
}

Ich habs das gleich in eine Toolbar gepackt zusammen mit Detach All, dann kann ich Visual Studio wieder davon lösen.

Von |2018-01-26T14:44:22+01:002018-01-12|EPLAN, EPLAN-Scripts|

Workaround: Projekteinstellungen werden nicht aktualisiert

Werden bestimmte Projekteinstellungen (wie z.B. Normblatt) geändert, kommt die Änderung zwar in der Oberfläche an, aber EPLAN “weiß davon noch nichts”.
Als Workaround einfach diesen Code nach dem Setzen der Einstellungen ausführen:

new EventManager().Send("PageManagement.ProjectSettings.Changed", new EventParameterString());
Von |2018-01-11T12:46:57+01:002018-01-11|EPLAN, EPLAN-Scripts|

GetVarLanguage

Im Kundenauftrag habe ich mich mal auf die Suche gemacht nach der Variablen Sprache. Diese bekommt man leider nicht so einfach, da es eine Projekteinstellung ist.

Anbei die Lösung. Einfach das Script laden und dann mit dieser Methode aufrufen. Somit kann man die Sprache in unterschiedlichen Scripten verwenden.
Vielen Dank an unseren tollen Kunden, für die Freigabe die Lösung hier zu veröffentlichen!

Aufruf:

private static string GetVarLanguage()
{
    string value = null;
    ActionCallingContext actionCallingContext = new ActionCallingContext();
    new CommandLineInterpreter().Execute("GetVarLanguage", actionCallingContext);
    actionCallingContext.GetParameter("value", ref value);
    return value;
}

 

Script:

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

namespace EplanScriptingProjectBySuplanus.GetVarLanguage
{
    public class GetVarLanguage
    {
        [DeclareAction("GetVarLanguage")]
        public void Action(out string value)
        {
            // Get language from settings
            string tempFile = Path.Combine(PathMap.SubstitutePath("$(TMP)"), "GetVarLanguage.xml");

            ActionCallingContext actionCallingContext = new ActionCallingContext();
            actionCallingContext.AddParameter("prj", FullProjectPath());
            actionCallingContext.AddParameter("node", "TRANSLATEGUI");
            actionCallingContext.AddParameter("XMLFile", tempFile);
            new CommandLineInterpreter().Execute("XSettingsExport", actionCallingContext);

            // Needed because there is no direct access to setting
            string language = GetValueSettingsXml(tempFile, "/Settings/CAT/MOD/Setting[@name='VAR_LANGUAGE']/Val");

            // If setting is GUI language, return the GUI language
            if (language == "##_##")
            {
                language = new Languages().GuiLanguage.GetString();
            }

            value = language;
        }

        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)
            {
                string value = rankListSchemaName[0].InnerText;
                return value;
            }
            return null;
        }

        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;
        }
    }
}

 

Wie immer auf GitHub zu finden :^)

Von |2019-03-14T08:36:45+01:002017-11-30|EPLAN|
Nach oben