Monthly Archives: February 2015

More exploring scripts – running EA Scripts from your code

I promised it wouldn’t be too long before I returned to provide the results from my experiments into running EA scripts from an external application (or if you wish from an EA Add-In).  If you missed the previous post on scripting may be worth reading first so that the current post is read in context.

Moving forward within exploring scripting capabilities let me start by providing some background information I discovered that will be relevant to the task in hand with the focus on user scripts.  You will see below I have skipped stuff that I didn’t see necessary for the current experiments.

1. EA stores its scripts in t_script

When we want to run an EA script we need to know where they can be found.  If you look into the EA database, and my suggestion would be to open a local EAP file using Access, you can find a table called t_script as illustrated below.

t_script - contains a range of scripts

t_script – contains a range of scripts including user scripts

If you look through that table you see the following columns which as I interpret have the following meanings:

  • ScriptID – a unique integer
  • ScriptCategory – there are several categories with normal human readable names and some GUID looking numbers (!) which including user scripts(indicated by the category with the value 605A62F7-BCD0-4845-A8D0-7DC45B4D2E3F).  You can also see other scripts such as those used when building code
  • ScriptName – once again either a human string or a GUID looking number
  • ScriptAuthor – another GUID looking number – not sure where this points to yet.  I’ll have to add this in when I find it but didn’t seem important at the time.
  • Notes – specifies the script name, type and language e.g.”<Script Name=”myScript” Type=”Internal” Language=”VBScript”/>”
  • Script – contains the script code in plain text form for user scripts.  When necessary I’ll have to check out the use of this for other types of scripts.

2. Extracting the script

If we want to run any of the user scripts we need to read the t_scripts table and extract the required script.  The method I have used was to:

  • Read the rows from the table, filtering on script category
  • Get the script name
  • For the selected script, extract the text from the Script column

3. Checks before running scripts

INCLUDES – If you look at scripts in EA you will see that some will include other scripts (e.g. INC). If we are running scripts within EA this is not a problem provided they exist within the EA context, however as we will see below, if we are running them elsewhere we need to ensure that we include ALL the relevant code.

RUN TIME OBJECTS – when running scripts within EA use is often made of the following run time objects:

  • Repository – current EA repository
  • Maths – the Cephes maths library
  • Session – which provides functions to interact with the user through the EA UI

If you are executing your scripts in another environment then you will need to supply the relevant references if required; note that the session object is purely for use within the EA script running environment.

Running scripts from the outside

With that bit of background we are now ready to look at running an EA script under the control of our “external” application.  Why is this an issue?  Can we not just ask EA to run the script for us?  Well so far I cannot see a way to interact with the EA script engine via the automation interface.  Hence,  the solution I have used (and I believe used by many others) is to provide my own instance of the script engine, extract the relevant script code and execute.

This isn’t as difficult as it sounds, although my voyage of discovery was interesting – and as seen from various posts on the Sparx Forum and Stack Overflow shared!

Script engine

As far as I can determine EA uses the Microsoft windows scripting engine.  Which I believe is MSScriptControl – which means that VB Script and JScript scripts written for EA can be run by using this control.

To run a script, we can use an instance of this class,  set the relevant attributes and call the run or execute function. So within our application we can:

  • Create an instance of MSScriptControl e.g. myScriptControl
  • Specify the script language e.g. myScriptControl.Language = “VBScript”
  • Set the script code using the relevant text (note: this will need to be complete with any includes expanded. e.g. myScriptControl.AddCode(ScriptCodeText)
  • If required pass objects that will be available to the script using the AddObject method e.g. myScriptControl.AddObject(“myObjectName”, myObjectValue, True) adds a name/value pair and sets this as a global value
  • If required pass parameters to the script.  This is done by setting up an object array containing the relevant arguments e.g. ArgumentObjects.  Remember that the scripting languages are loosely typed so they have no explicit knowledge of typing
  • We can then run the script and for functions capture the result e.g. myResult = myScriptControl.run(“myScriptName”, ArgumentObjects)

Pulling it all together

So with that background I put together a simple program to run a script.  The application provided a means to enter a script and run it.  This allowed me to verify that the mechanism worked fine without any interactions with EA.  However, I need to remember to do things link reset the scriptcontrol if I reuse it (myScriptControl.reset)!

It is also worth noting that I recently saw that there are some observed issues, for example – adding code will automatically execute code – I have only seen this issue when executing the script control within an EA Addin, it seemed to work fine when operating in a standalone program but that doesn’t mean there aren’t instances where this is not the case (the joys of software), hence I need to explore further!

But in the meantime, onto testing with EA – which involves the following steps:

  • Open an EA Repository
  • Get a list of user scripts
  • Select and run a script
  • View the result report

As it turned out I skipped writing a simple windows application as I was confident that would work, so went straight to writing a small Add-In that would perform these tasks. So no need to open the repository just the steps that followed.

My simple Add-In basically lists the available user scripts and provides a means to inspect and run the script.

Script Tester Menu

Script Tester Menu

The form that presents me with a list of scripts (as well as providing a option to refresh the list) is illustrated below.

Script tester list of scripts

Script tester addin displays a list of scripts that can be selected

The user can select a script from the list, and inspect the details:

Script Details

Details of selected script – script can be run by pressing run script button

And if they wish run the script, for example as below.

Results from running the simple script

Results from running the simple script

I am pleased to say that it presented the same result as when running the script natively within EA.

So using this approach there is a a means to run EA scripts under our control, demonstrated with this EA Add-In, and I’m confident it will work from the outside with a windows application, albeit with care regarding the objects that are being expected.

Points to note

Just to recap on the some points for running scripts using the script control.  You need to:

  • Ensure that the code provided is complete
  • Reset the script control before use
  • Pass any required object to the script – note that session is not available and if libraries are required you are responsible for ensuring that they are accessible
  • Provide any required arguments as objects – NOT typed
  • Capture the results

Nearly there or not!

If I refer back to my diagram in the last post (repeated here for reference), that illustrated all the tests I wanted to explore.

Overview of scripting scenarios to explore

Overview of scripting scenarios to explore

We have covered all cases 1 to 6 – albeit that there is ongoing work in checking some potential issues with case 6.

Case 7 – calling our Add-In from a script when working within EA

So what about the EA script control (not our own script control) calling an EA Add In. Just to be clear this is a normal EA script running within EA.  Is there a way?  Well I’m still working on this. I’ve posted and had some interesting observations which I have posted on the Sparx Forum.

This case has presented some interesting windows programming issue which has forced me to spend more time that planned looking into windows processes, but then that is the fun of exploring.

Overall for the most likely use cases all works as one would hope.  It is the edge cases that I thought I needed to explore that have raised some issues and I’ll be looking into:

  • Feedback I’ve received on how to resolve case 5
  • Unwanted code execution issues in case 6
  • Finding the correct reference for case 7

I hope to report back soon with my findings for these cases.

In the meantime, if you have some answers do join the dialogue here or on the forums.  For those happy with other scenarios I hope you have found this useful.

Adrian

 

Advertisements

More exploring scripts – looking at application interoperability

In my last post on scripting  I was looking at using scripts as part of customising EA.    When I finished the last post I was part way through my exploration of “Application Interoperability”. So let me continue, but I must warn you that in this post I won’t be covering too much that is unique to scripting, however it is nevertheless useful stuff that provides some groundwork for subsequent experiments into scripting.

Last time I looked at how a script can gain access to an application such as Excel which can operate as a COM server.  My next set of experiments looked into if and how scripts could interact with code that I’d developed outside of EA, for example, a windows application or from one of my own class libraries (DLL).

To provide a sense of what I was thinking about let me use a diagram to illustrate theses and other options I am exploring.  In the diagram I show EA and its repository together with several other components that may be treated within the current context as being “internal” to EA’s operating environment plus several components that clearly site “outside of the box”.   I have treated everything that EA knows about including any registered AddIns as being inside,  the others, which EA doesn’t know about, are outside.

To guide us through the experiments I have numbered the connections to represent each specific test; remember we are in the world of experimenting, so I am just illustrating capability, whether or not it is of any value is another story.

Overview of scripting scenarios to explore

Overview of scripting scenarios to explore

Overview of interoperability scenarios to explore

1. Calling my Class Library (DLL) from an EA script

This is a relatively straight forward case since it is just another example where we use our script to create an application object,  but in this case the object (DLL class) is one I created.  Of course, there are some rules, for example when we create our class library we must:

  • provide suitably accessible public methods
  • our library needs to be registered as a COM object so that Windows is aware of the class when our script wants to use it.

So here is the code for my class library – very simple.

 Public Class MyEACalledClass
 Public Sub New()
    MsgBox("Hello from my DLL")
 End Sub
 End Class

This class is compiled as a library and then registered for COM interop using regasm, this is the same way that we register an  EA AddIn – see my post One of our Addins is missing for more information.

And then within our EA model we can create a script that calls this class as illustrated in  the screen shot.  When the script runs we get the message box that we have in the class constructor.

Calling my own class library

Calling my own class library

So we have address case 1 – now into case 2.

(2) my DLL can access EA repository

We can extend the functionality of the class library (DLL) as we wish.  For example, we may want our library to perform some functions that involve interacting with the current EA repository.  To do this we simply need to:

  • Write the relevant EA code in our class library (linking with Interop.EA.dll)
  • At run time, we need the script to pass the current EA repository object to our class library

Below is a trivial example.  The setEAModel receives the current EA repository object which is stored locally and then the getEAModelInfo method interacts with EA and returns a value to the calling process, in our case as shown below a simple script.

Private myRepository As EA.Repository = Nothing
Public Sub setEAModel(pRepository As EA.Repository)
  myRepository = pRepository
End Sub
 Public Function getEAModelInfo() As String
 If myRepository IsNot Nothing Then
 Dim myInfoString As String = myRepository.ConnectionString
 Return myInfoString
 End If
 Return "No report"
 End Function

Here is an example script calling our class library and getting information back relating to the current repository.

Calling EA from our DLL

Calling EA from our DLL

Clearly we wouldn’t create a library to perform such a trivial task which can be done locally. However, there may be situations where you want other functions such as interacting with another application / service that cannot be done within a script, but doesn’t warrant the need to create an EA addin, and hence this could be an option.

 (3) / (4) Windows application using our class library and interacting with EA repository

The next 2 examples look at using a windows application as a EA client, firstly just accessing the EA repository and then accessing and running a script.

The first test case (3) of access our own DLL is purely windows and an everyday task for windows application developers, so no more on that.

As with any other windows application you need to ensure that you include the relevant library(s) that supports interoperating with EA ( Interop.EA.dll) which exists in the EA installation directory.  Then to connect to EA:

  1. Create a new EA.Repository object (e.g. myEARepository)
  2. Open your file( or EA server) using myRepository.OpenFile(filenamestring)
  3. Perform required functions as required.

If you are new to working with the EA API I would suggest getting a copy of Scripting Enterprise Architect by Thomas Kilian – it goes through most stuff that you may want to do when working with EA.  And if that isn’t sufficient then check out Sparx Systems Automation Forum

So why would we produce a windows application as an EA client? The simple reason is that you want to provide a client that performs specific functions that do not require the use of the EA UI, for example:

  • to reduce complexity for the user – I have developed clients that make it easy to work with an EA model, as illustrated below a very simple interface with an application that can be provided to new users or more specifically in my case to those resistant to starting to use EA
Example of an EA client

Example of an EA client

  • to provide interaction with a 3rd party application
  • to run automatically to perform some house keeping tasks on the repository – this allows the application to be scheduled with windows Task Scheduler.

BTW: In relation to working with EA I have found it really useful at time to produce a small windows application accessing EA as an external application.  I have developed a small template application which provides the basic infrastructure for interacting with EA, selecting and opening a repository and providing basic element functions that I continually reuse when testing stuff.

(5) Accessing and running EA script’s from the outside

For the final experiment today, I was looking at a means for an external windows application to make a call to EA, and for EA to run a requested script for us. For example, there can be scenarios when you want to run a script on an automatic basis.

As far as I can see EA doesn’t provide a means to open EA from a command line, run a script and close.  The nearest I can see is the Project Shortcut – which nearly fulfils the requirements except that it doesn’t appear to provide a means to run a suitable script of my choice.  Is there a mechanism?

Well in the meantime it looks like I will have to create an application that will open my repository and execute the scripts.  So how can this be done – well as I started I see it’s not a short answer so I’m going to dedicate my next post to that task, as well as look at possible interactions between EA Addins and EA scripts. I’m already writing it so won’t be long.

In the meantime I hope this was of interest.

Any queries about this or other scripting issues let me know as I could add them to my expanding list of scripting experiments.

All the best

Adrian

Using eaForms to hide tagged values (and improve the quality of your model)

Tagged values are used extensively since they allow us to customise the information we store for our elements. So unlike pre-defined fields we can add them as we require to match the needs of our project. Also within EA we can specify the type and, for some types valid values.  So that’s all great.

Within EA, tagged values can be accessed in several ways. For example, they are available as a tab of the element properties editor or can be accessed via a separate tagged values window. However,  this does mean that the user needs to remember to switch to the relevant place to enter values.  And although there is often the option to set a default value, there is no check that a value has been entered by the user, and hence it may be that the value is a true reflection of the authors input.

We believe this leaves some room for errors and/or incomplete information when editing elements.  So in eaForms we have provided some features which we believe can help users when creating and editing elements.

  • For a start eaForms presents tagged value in the same way as other element fields, with all the same window controls – whether it be a text field, checkbox, rich text box, drop down list, etc – and hence can better reflect the type of input required and simplify data entry
  • The eaForms designer can set pre-defined values to help ensure consistency of values across the model
  • The eaForms designer can also mandate the need for a valid value and hence ensure that data is entered, which in turn can help drive completeness

Although simple these features not only hide some of the fiddly stuff associated with using tagged values, but also help improve the quality of the model.

To illustrate we have some sample screen shots below that show the use of different controls for tagged values.  (Note: these features can be applied across all elements, stereotypes and MDG’s)

Example eaForm showing the use of common windows controls for data entry

Example eaForm showing the use of common windows controls for data entry

On the left we have used several check boxes to capture choices. On the right is a rich text box used to allow them to provide more detailed information.  And on the top right we have a drop down where the user must select a value, no default value has been set and in the definition of the form we have flagged the field as mandatory.   If the user fails to enter a value they are reminded that it is required before they can save their edit.

Example of eaForm warning when required (mandatory) field value not set

Example of eaForm warning when required (mandatory) field value not set

And we must remember that our aim, as always, is to simplify the work of the user who has the knowledge that we need in our model.  So in removing the need to switch to a different place to enter information, by consolidating it all onto a single form in a consistent manner, we can help the user focus on the task in hand.

So just to recap – eaForms:

  • Treats tagged values in the same way as other element fields – easier for user to understand
  • Offers a range of different windows controls for editing including those that force a selection from pre-defined values
  • Allows fields to be flagged as mandatory to ensure completeness of content

Just one small aid to helping getting the job done – I hope you agree.

Click for more information on eaForms