Home > Sparx Systems Enterprise Architect > Tutorial: Create your first C# Enterprise Architect addin in 10 minutes

Tutorial: Create your first C# Enterprise Architect addin in 10 minutes

Enterprise Architect from Sparx Systems is a great UML Case tool, but you can make it even better by adding your own functionality in the form of an add-in.

This post will take you through the basic steps to create your first C# EA add-in  in about 10 minutes.

You can use a number of programming languages to create add-ins for EA, but personally I like C# the best.

Prerequisites

Before you start you should have following software on your computer ready to use:

  • Enterprise Architect (download the fully functional trial if you don’t have it installed yet)
  • Visual Studio (I’m using the free Visual C# 2010 Express for this tutorial)

EA’s addin architecture

To fully understand the steps necessary to get your add-in running you should first understand how EA’s add-in architecture works.

When EA starts up it will read the registry key [HKEY_CURRENT_USER\Software\Sparx Systems\EAAddins]. Each of the keys in this location represents an add-in for EA to load.

The (default) value of the key contains the name of the assembly and the name of the add-in class separated with a dot.

EA then asks Windows  for the location of the assembly, which is stored on the COM codebase entries in the registry, and it will use the public operations defined in the add-in class.

So in order for our add-in to work we’ll need to:

  • Create the add-in dll containing the add-in class
  • Add a key to registry containing the name of the assembly and the name of the add-in class
  • Register the in the COM codebase entries in the registry

Step 1: Create the add-in dll

So open up Visual Studio, start a new project, and choose Class Library as type of project.

The first thing we need to do is to add the EA API assembly to our references, so choose Add Reference….

Select the Browse tab, browse tot the EA installation folder (default: C:\Program Files\Sparx Systems\EA) and choose the file Interop.EA.dll.
This will allow us to use the classes/interfaces defined by EA’s API.

And since we will be using a messagebox for our first addin, select the .NET tab, scroll down and select System.Windows.Forms

Then there are some build options we need to configure.
First we’re going to tell Visual Studio to build our dll so it can be used as a COM object.
Doubleclick on on the properties folder under your project, click on the button Assembly Information and tick the little checkbox on the bottom that says Make assembly COM-visible

Then we would also like Visual Studio to register the dll in the COM codebase entries in the registry each time it builds our little project.

To do so go into the Build tab of the project properties and tick the checkbox Register for COM interop.

Then we rename the default Class1.cs to MyAddinClass.cs and replace the existing template code by the following:

using System;
using System.Windows.Forms;

namespace MyAddin
{
    public class MyAddinClass
    {
        // define menu constants
        const string menuHeader = "-&MyAddin";
        const string menuHello = "&Say Hello";
        const string menuGoodbye = "&Say Goodbye";

        // remember if we have to say hello or goodbye
        private bool shouldWeSayHello = true;

        ///
        /// Called Before EA starts to check Add-In Exists
        /// Nothing is done here.
        /// This operation needs to exists for the addin to work
        ///
        /// <param name="Repository" />the EA repository
        /// a string
        public String EA_Connect(EA.Repository Repository)
        {
            //No special processing required.
            return "a string";
        }

        ///
        /// Called when user Clicks Add-Ins Menu item from within EA.
        /// Populates the Menu with our desired selections.
        /// Location can be "TreeView" "MainMenu" or "Diagram".
        ///
        /// <param name="Repository" />the repository
        /// <param name="Location" />the location of the menu
        /// <param name="MenuName" />the name of the menu
        ///
        public object EA_GetMenuItems(EA.Repository Repository, string Location, string MenuName)
        {

                switch (MenuName)
                {
                    // defines the top level menu option
                    case "":
                        return menuHeader;
                    // defines the submenu options
                    case menuHeader:
                        string[] subMenus = { menuHello, menuGoodbye};
                        return subMenus;
                }

            return "";
        }

        ///
        /// returns true if a project is currently opened
        ///
        /// <param name="Repository" />the repository
        /// true if a project is opened in EA
        bool IsProjectOpen(EA.Repository Repository)
        {
            try
            {
                EA.Collection c = Repository.Models;
                return true;
            }
            catch
            {
                return false;
            }
        }

        ///
        /// Called once Menu has been opened to see what menu items should active.
        ///
        /// <param name="Repository" />the repository
        /// <param name="Location" />the location of the menu
        /// <param name="MenuName" />the name of the menu
        /// <param name="ItemName" />the name of the menu item
        /// <param name="IsEnabled" />boolean indicating whethe the menu item is enabled
        /// <param name="IsChecked" />boolean indicating whether the menu is checked
        public void EA_GetMenuState(EA.Repository Repository, string Location, string MenuName, string ItemName, ref bool IsEnabled, ref bool IsChecked)
        {
            if (IsProjectOpen(Repository))
            {
                switch (ItemName)
                {
                    // define the state of the hello menu option
                    case menuHello:
                        IsEnabled = shouldWeSayHello;
                        break;
                    // define the state of the goodbye menu option
                    case menuGoodbye:
                        IsEnabled = !shouldWeSayHello;
                        break;
                    // there shouldn't be any other, but just in case disable it.
                    default:
                        IsEnabled = false;
                        break;
                }
            }
            else
            {
                // If no open project, disable all menu options
                IsEnabled = false;
            }
        }

        ///
        /// Called when user makes a selection in the menu.
        /// This is your main exit point to the rest of your Add-in
        ///
        /// <param name="Repository" />the repository
        /// <param name="Location" />the location of the menu
        /// <param name="MenuName" />the name of the menu
        /// <param name="ItemName" />the name of the selected menu item
        public void EA_MenuClick(EA.Repository Repository, string Location, string MenuName, string ItemName)
        {
            switch (ItemName)
            {
                // user has clicked the menuHello menu option
                case menuHello:
                    this.sayHello();
                    break;
                // user has clicked the menuGoodbye menu option
                case menuGoodbye:
                    this.sayGoodbye();
                    break;
            }
        }

        ///
        /// Say Hello to the world
        ///
        private void sayHello()
        {
            MessageBox.Show("Hello World");
            this.shouldWeSayHello = false;
        }

        ///
        /// Say Goodbye to the world
        ///
        private void sayGoodbye()
        {
            MessageBox.Show("Goodbye World");
            this.shouldWeSayHello = true;
        }

        ///
        /// EA calls this operation when it exists. Can be used to do some cleanup work.
        ///
        public void EA_Disconnect()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

    }
}

Now all we need to do is build the project, and the add-in dll is finished.

Step 2: Add the registry key

In order to let EA know there is a new add-in to be loaded we need to add a key in the registry in the location: HKEY_CURRENT_USER\Software\Sparx Systems\EAAddins

To do so open up the Windows registry editor by clicking Start|Run and type regedit

Then browse to the HKEY_CURRENT_USER\Software\Sparx Systems\EAAddins key, right click and add a key with the name of the project in Visual Studio, in our case MyAddin

The registry editor will automatically create a default value for the new key. Doubleclick on the (Default) value on the right pane, and enter the value in the form of [ProjectName].[ClassName], so in this case MyAddin.MyAddinClass

Step 3: Try it out in EA

Alright, now the add-in is ready to be used. So fire up EA, open a project and right click on an element in the projectbrowser, or a diagram.

You should now see an additional menu option with the options we defined.

Congratulations! You have just created your first C# add-in for EA

Distributing the add-in

Once you have finished your add-in you will probably want to share it with others.

There are three steps needed to install your add-in on another computer:

  1. Copy the required files to a convenient location.
    You can find the files needed in your Visual Studio project folder: ..\MyAddin\MyAddin\bin\Release
  2. Register your add-in dll in the COM codebase entries in the registry using regasm.exe
    Open up a command prompt in folder where you copied the add-in dll and register the dll with the /codebase option. In my case that command would be: %WINDIR%\Microsoft.NET\Framework\v4.0.30319\regasm MyAddin.dll /codebase
  3. Add the registry key
    The easiest way to add the registry key on another computer is to export the key from your registry using regedit. This will save the information stored in the key in a .reg file, which you can execute by doubleclicking.

These three steps can of course be automated by your favorite installer program.

More resources

About these ads
  1. Lauren Arce
    06/10/2011 at 19:15 | #1

    Hi Geert,

    I am developing my first add-in for EA so I went through the steps above and got the following errors when building the code:

    Error 1 A namespace cannot directly contain members such as fields or methods C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 3 1 MyAddin
    Error 2 { expected C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 7 22 MyAddin
    Error 3 A namespace cannot directly contain members such as fields or methods C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 9 1 MyAddin
    Error 4 { expected C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 11 34 MyAddin
    Error 5 Invalid token ’007′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 13 1 MyAddin
    Error 6 Invalid token ’010′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 19 1 MyAddin
    Error 7 Invalid token ’011′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 21 1 MyAddin
    Error 8 Invalid token ’012′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 23 1 MyAddin
    Error 9 Invalid token ’015′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 29 1 MyAddin
    Error 10 ; expected C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 45 63 MyAddin
    Error 11 Invalid token ’024′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 47 1 MyAddin
    Error 12 ; expected C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 75 102 MyAddin
    Error 13 Invalid token ’039′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 77 1 MyAddin
    Error 14 Invalid token ‘)’ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 81 37 MyAddin
    Error 15 Invalid token ‘;’ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 89 46 MyAddin
    Error 16 Invalid token ‘:’ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 93 40 MyAddin
    Error 17 Invalid token ’049′ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 97 1 MyAddin
    Error 18 Invalid token ‘;’ in class, struct, or interface member declaration C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 97 44 MyAddin
    Error 19 A namespace cannot directly contain members such as fields or methods C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 101 1 MyAddin
    Error 20 A namespace cannot directly contain members such as fields or methods C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 107 1 MyAddin
    Error 21 Expected class, delegate, enum, interface, or struct C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 163 20 MyAddin
    Error 22 Expected class, delegate, enum, interface, or struct C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 233 20 MyAddin
    Error 23 Expected class, delegate, enum, interface, or struct C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 269 21 MyAddin
    Error 24 Expected class, delegate, enum, interface, or struct C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 287 21 MyAddin
    Error 25 Expected class, delegate, enum, interface, or struct C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 305 20 MyAddin
    Error 26 Type or namespace definition, or end-of-file expected C:\Users\lauren.arce\AppData\Local\Temporary Projects\ClassLibrary1\MyAddinClass.cs 317 9 MyAddin

    Any idea where I may have gone wrong?

    Ultimately, my goal is to write an add-in to import milestones dates from an MS Project file into EA as class attribute values.

    Thanks in advance for your help!

    -Lauren

  2. Lauren Arce
    06/10/2011 at 19:22 | #2

    Geert,

    I’ve repasted the code and now I only get the following errors:

    Error 1 The type or namespace name ‘EA’ could not be found (are you missing a using directive or an assembly reference?) C:\Users\lauren.arce\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\MyAddinClass.cs 23 34 MyAddin
    Error 2 The type or namespace name ‘EA’ could not be found (are you missing a using directive or an assembly reference?) C:\Users\lauren.arce\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\MyAddinClass.cs 38 39 MyAddin
    Error 3 The type or namespace name ‘EA’ could not be found (are you missing a using directive or an assembly reference?) C:\Users\lauren.arce\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\MyAddinClass.cs 60 28 MyAddin
    Error 4 The type or namespace name ‘EA’ could not be found (are you missing a using directive or an assembly reference?) C:\Users\lauren.arce\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\MyAddinClass.cs 82 37 MyAddin
    Error 5 The type or namespace name ‘EA’ could not be found (are you missing a using directive or an assembly reference?) C:\Users\lauren.arce\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\MyAddinClass.cs 117 34 MyAddin

    Any idea what the issue may be?

    Thanks again.
    -Lauren

  3. Lauren Arce
    06/10/2011 at 20:01 | #3

    Geert,

    I was able to fix the errors — as it turns out I never added the “Interop.EA.dll” as a reference.

    I am now able to build without any errrors, but I cannot see the add-in in EA yet. When I go to the manage add-ins menu in EA, it says that MyAddin is “Error-Missing”??

    -Lauren

  4. Lauren Arce
    06/10/2011 at 20:06 | #4

    Geert,

    Not sure what happened, but it now shows up in EA! Maybe my computer is just slow … nice!

    Now off to figure out how to tweak the code to do what I want it to do …

    -Lauren

    • 07/10/2011 at 08:33 | #5

      Hi Lauren,

      I’m glad to see that you managed to get it working.

      Geert

      • Lauren Arce
        07/10/2011 at 19:46 | #6

        Hi Geert,

        On an unrelated topic, do you know the distinction between “attribute values” and “tagged values” in EA? EA Version 9.1.910 now has the ability to export/import tagged values.

        Thanks.
        -Lauren

  5. Lauren Arce
    20/10/2011 at 20:58 | #7

    Hi Geert,

    Any insight on whether it is good practice to use attributes initial values or tagged values? The reason I ask is because I have the need to import and export data (both ways) from an MS Excel file on a routine basis to update the model so I want to be able to do this in the most automated manner. The CSV import/export works great in doing this with tagged values, but with attributes the closest option is your “Simple VBA Excel to EA importer” macro. And, as far as I can tell, your macro will not import an attribute initial value and I cannot export the same information out of EA to MS Excel.

    Thanks.
    -Lauren

    • 21/10/2011 at 02:32 | #8

      Lauren,

      Attribute initial values and tagged values are different things, each designed for a specific purpose. I think you should use them for their intended purpose only.
      If you want to import initial values into EA it should not take more then half an hour to add that function to the Excel VBA. Have you tried that?

      • Lauren Arce
        21/10/2011 at 19:16 | #9

        Geert,

        I have not taken a stab at trying to add the function to the Excel VBA. I’ll take a look. How difficult do you think it would be to modify the code to do an export from Excel as well? Ultimately, I need the import/export capability that includes attribute name, attribute data type, attribute length, attribute initial value, and possibly tagged-values between EA and Excel.

        Could you elaborate on when one should use attributes vs. tagged values? An example may be helpful.

        Thanks again for all your insight.

        -Lauren

  6. Murat Cinar
    08/12/2011 at 22:05 | #10

    Hi,
    I am working on an add-in for EA, when I was developing the add-in, Visual studio was successfully able to register it as a COM object, but after I finished developing, I copied the dll’s to a specific location on another computer, registered them using regasm.exe (with every possible combination of with or without /codebase option or with or without /tlb option) I also tried to register it using both regasm.exe’s under Framework64 and Framework, but it did not worked. Since I put the last registry manually, I am able to see that EA knows about the add-in but says Error-Missing in the manage add-ins part. I even tried to create regfile and apply it by double clicking but I think all above had the same effect, more or less..
    I would appreciate if you know how to solve this problem. (the O.S I tried is a Windows7 64bit)

    Thank you,
    -Murat

    • 09/12/2011 at 05:15 | #11

      Hi Murat,

      I can think of two possible explanations for the “error missing” problem
      - The Addin dll has not been correctly registered as a COM object
      - There’s a spelling error in the value of the addin registry key

      What I would try is to create an installer for the addin and install it like that on the other machine.
      There’s an easy installer option in VS, but in case you don’t have the correct VS package you could give wix a shot.
      I’ve written a tutorial on that here:
      http://geertbellekens.wordpress.com/2011/02/23/tutorial-deploy-your-enterprise-architect-csharp-add-in-with-an-msi-package/

      Geert

      • Murat Cinar
        13/12/2011 at 18:12 | #12

        Hi Geert,
        Thank you so much for your help. Right now, it is working perfectly with WIX installer.

        Murat.

      • Albina
        16/10/2012 at 10:23 | #13

        Hello Geert,

        I have the same issue: EA knows about the add-in but says Error-Missing in the manage add-ins part. I’ve use your code and your MyAddin project, but it did not solve my problem. Where should be a problem?

        Thanks

      • geertbellekens
        16/10/2012 at 11:13 | #14

        Albina,

        As I told Murat and the others, it either a problem with the COM registration of your dll, or a spelling error in the registry key.
        Make sure you run your IDE as administrator, and select the options to register for COM interop.

      • Albina
        23/10/2012 at 14:36 | #15

        Thank you very much for your replay.

        I don’t understand the problem. I’m running the VS in admin mode and the COM Interop is selected. I tried many times to create MyAddin project and only once it did work and EA did see MyAddin. I created the installer and it worked on some workstation properly, but on the rest…. I’ve installed Framework 4 on all our machines. Something is wrong, but what? Something small :(.

      • GeeBhawllar(Bola)
        12/12/2012 at 17:35 | #16

        Hi Geert,

        I dont know whether you have any tips for me.

        I have been trying to use the Visual Studio/TFS MDG to import and synchronize TFS work items with EA….. I have followed all the suggested steps in http://www.sparxsystems.com/bin/MDGIntegrationVS4.pdf

        Everything worked until i click select the Team Foundation Server | Import Work Items. Then i get an error message that says i am not connected to TFS. I have already added an existing EA model, i have linked a visual studio project to an existing EA model package, i have specified the MDG integrate option, I have been able to play around the EA model in Visual Studio (added new elements etc)…….What could i have done wrong

        Thanks

        Bola

      • 12/12/2012 at 17:55 | #17

        Hi Bola,

        No, sorry I can’t help you with that.
        I would first try the forum http://www.sparxsystems.com/cgi-bin/yabb/YaBB.cgi and otherwise contact Sparx support.

        Geert

      • GeeBhawllar(Bola)
        18/12/2012 at 15:29 | #18

        Hi Geert,

        Thank you….i got an excellent reply from Sparx Support, now i can connect TFS work items to EA elements…. for us, whether we use tfs or ea has become irrelevant. we create an excellent model and when its time to build, we use visual studio. In tfs, bugs will be created as work items and then we can bring them back to EA as elements……Slick. Thank you again

        Bola

  7. Guillaume
    12/08/2012 at 21:45 | #19

    Hi Geert,
    Do you reckon there could be an impact when you choose the dotNet framework version when you create a new project, e.g. between version 2 and 4? I guess v4 will require all users to have or upgrade to this version? Does version provide all that’s necessary so it’d be fairly useless using v4?
    Thanks

    • 13/08/2012 at 06:13 | #20

      Hi Guillaume,

      Yes if your users don’t have the .Net framework version 4 installed yet, they would have to install that before being able to run any program compiled against .Net 4.
      Whether or not you want to use version 4 depends on your own preferences, and whether or not you want to use one of the new features in version 4. I’m no .Net specialist, so I don’t really know the differences between the two frameworks.

      Geert

  8. Wolfgang
    31/08/2012 at 09:15 | #21

    Hi Geert,
    great tutorial, thank you. I have a question regarding events. Since an element change is triggering an event, I thought to use that as a means to increment the version. Unfortunately it seems not to work when the scenario of an element changes. Or did I miss something here?
    Can you give me a hint here?

    Thanks
    Wolfgang

    • 31/08/2012 at 09:40 | #22

      Wolfgang,

      I’m not surprised. API support fro scenario’s is poor to say the least.
      They do have these type of events for all types of tagged values, but apparently not for scenarios.
      The only advice I can give you is to submit a feature request to Sparx

      Geert

  9. David Rains
    01/09/2012 at 01:26 | #23

    Hi Geert,
    Finally getting around to jumping from scripts to the addin world :) I am using 2010 version of C# Express and am logged in an administrator on my laptop. When I buidl the project I get ONLY the following error msg?

    Error 1 Cannot register assembly “C:\Users\DRains\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\bin\Release\MyAddin.dll” – access denied. Please make sure you’re running the application as administrator. Access to the registry key ‘HKEY_CLASSES_ROOT\MyAddin.MyAddinClass’ is denied.

    Thanks again for all the effort you put into supporting the EA community!

    David (aka bioform) Rains, MD – USA

  10. David Rains
    01/09/2012 at 01:38 | #24

    Geert,

    Okay found out that I had EA up and running, so shut it down and it complied fine no errors.
    So know ran regedit – but my registry does not list ‘HKEY_CURRENT_USER\Software\Sparx Systems\EAAddins”, it is ‘…\EA400′ instead of ‘\EAAddins’ ?!! The next two children are \EA and \SSCE neither of which contain the one I am looking for? Running EA 9.3 Build 934 on a Windows 7 (64 bit) but EA installed as 32 bit application.

    Thanks again,
    David ‘going bald over this’ Rains ;)

    • 01/09/2012 at 08:42 | #25

      Hi David,

      If you’ve never installed an add-in before then it would be logical that the EAAddins key doesn’t exist yet in the registry.
      You just have to create it yourself.

      Geert

      • David Rains
        01/09/2012 at 15:50 | #26

        :) Still plugging away on this…
        Got the registry key entered and string defined. Checked my spelling and every things seems to match.

        …\EAAddins\MyAddin then added string value: MyAddin.MyAddinClass (verified that the namespace and class name are correct)

        Rebuilt add-in, then got the Error-Missing msg within EA.

        So I “repaired” .Net 4, rebooted, rebuilt, and started EA… same problem. Grrrr ;)

        David

  11. 01/09/2012 at 17:47 | #27

    David,

    I you have the dreaded “error-missing” error then it means that the registry key is being read OK.
    Now you probably just have a problem with the COM registration of your dll.

    Geert

  12. David Rains
    02/09/2012 at 04:20 | #28

    Just a problem with… Now your messing with me Geert! :)
    Okay I spent some time trying to figure this out, looking at old posts, etc.

    you had mention using regasm with the /codebase option…
    Since I am using VS2010 express it appears that it is not included with that version.

    any comments?

    • 02/09/2012 at 09:51 | #29

      I think regasm is part of the .net distribution, so it shouldn’t matter which version of VS you are using.
      But you shouldn’t need regasm on the development machine. You should just tick the “Register for COM interop” checkbox somewhere in the project properties. (Assembly I think)

  13. David Rains
    04/09/2012 at 01:58 | #30

    Geert,

    I have spent a good part of this weekend trying to get past the EA “error- missing” issue. I have been using the ‘Register for COM interop” checkbox during this whole process, but can’t seem to find a solution.

    Pretty much in the same spot I was in a couple of years ago when I tried this under VS 2005 on a different PC and laptop?!!

    Almost ready to through in the towel and reload everything from the ground up, but I have a bad feeling that would not fix this issue either?

    Previously I had tried to get this to work under VS 2008 Pro, but same problem was happening with any add-in I tried to create….

    David

    • David Rains
      04/09/2012 at 02:05 | #31

      I believe I previously mentioned that I am running Win 7 64 bit, does that have anything to do with it? I was reading the notes about using regasm with /codebase option and how you had to explicitly reference the 32 bit version…

      David ‘Grasping at Straws’ Rains :)

      BTW I am installing EA Nav to see if that will work for me as I am not running any-addin right now. I’ll let you know how that goes.

  14. 04/09/2012 at 07:08 | #32

    David, there must be some small stupid thing you are overlooking.
    Have you tried with my example add-in: https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/tree/master/MyAddin
    If that doesn’t work you can may always zip up the whole project and send it to me by email, maybe I can spot the problem.

  15. David Rains
    14/09/2012 at 02:28 | #33

    Geert,

    Well, just installed 2012 VS Express, ran and compiled add-in no errors with the same result.
    Then tried ‘Run Code Analysis on MyAddin’ and found this error (not code related):

    Error 1 Cannot register assembly “C:\Users\DRains\Documents\Visual Studio 2010\Projects\MyAddin\MyAddin\bin\Release\MyAddin.dll” – access denied. Please make sure you’re running the application as administrator. Access to the registry key ‘HKEY_CLASSES_ROOT\MyAddin.MyAddinClass’ is denied.

    So I am logged in with full admin rights… so maybe getting closer to an understanding of the problem I believe. Going to try this again after I create a new admin account and see what happens. BTW I sent you the code as a zip a week or so ago – any chance to take a look?

    Thanks

    David

    • David Rains
      14/09/2012 at 03:04 | #34

      Same Issue! So it looks like the error is telling me the problem – but not sure what to do about it?! ;) Any thoughts?

      David

    • 14/09/2012 at 07:21 | #35

      David,

      I just searched my email box, but I didn’t find any emails from you. Maybe it was stopped by my spam filter.
      Anyway, the problem with the registration of the assembly is because you are not running the application (VS) as administrator.
      Instead of just doublicking the Visual Studio icon you have to right click and choose “run as administrator”; even if your account is already an administrator.
      That is one of the differences between Windows XP and Windows 7

      Geert

      • David Rains
        14/09/2012 at 15:26 | #36

        :) Works like a charm NOW! Had to unselect in EA, restart, select in EA, restart.

        Look out world I’m back! LOL I will keep you informed of my proof-of-concept structured business vocabulary (SBV) work.

        Thanks again as always Geert,

        David

      • 18/09/2012 at 07:51 | #37

        Cool, yes maybe I forgot to mention, you cannot build your add-in when EA is running your add-in (because it is then using the dll).
        That is the reason why I use the add-in tester class. That allows me to test part of my add-ins (menu functions) without having to run the add-in through EA.

      • GeeBhawllar(Bola)
        05/12/2012 at 02:14 | #38

        Hey Geert,

        I dont really understand “you cannot build your add-in when EA is running your add-in (because it is then using the dll).”…. are you saying EA should not be running when you are building the add in?

      • 05/12/2012 at 04:49 | #39

        Yes indeed. You either have to shut down EA or make sure EA hasn’t loaded your add-in (Extension|Manage Add-ins) when building your code.
        Otherwise the dll is in use and you cannot overwrite it.

      • GeeBhawllar (Bola)
        05/12/2012 at 05:37 | #40

        Thank you Geert,

        I have actually been able to get this to work as you described it, what i have been doing is building on it and i dont seem to be making much progress.

        My real problem was stated on EA community site “I have an activity diagram that contains some action elements in swim lanes or partitions. Some swim lanes have more than one partition.

        I am trying to count the number of action items in each partition and then save it in a temporary csv file, total count for each partition will be saved separately from the next partition……. persisting the information in a csv file is not a big problem, the issue i have been trying to solve is whether each action item is an element within the partition element. if so, can the partition be a collection of action elements so that i can set a counter for each partition?

        I am actually trying to build a dashboard that gives a realtime information about the elements located in each partition ….. if you have some materials on how to customize dashboards for displaying project information, i will appreciate it

        Thanks

        GeeBhawllar

        GeeBhawllar

      • 05/12/2012 at 08:26 | #41

        Gee,

        Seems to me like you have two challenges
        - How to figure out if an action is part of a partition
        - How to display “real time” information on this type of information

        For the first challenge, EA should nest the actions in the appropriate ActivityPartition when you move them on such a partition on the diagram. So you can get a list of action if you use the Elements collection of the ActivityPartition Element. But beware, this only counts for ActivityPartitions, not for swimlanes. Swimlanes in EA are a purely visual thing, they don’t really represent anything.

        As for the “real-time” information, I think the best thing you can do is use some kind of polling mechanism to figure out is the numbers have been changed.
        You could of course use the EA events like EA_OnContextItemChanged to check whether or not the user did something with an action you are interested in, but that process would be error-prone. It would be enough if one user had disabled your add-in for your numbers to be wrong.
        So the safest thing would probably be the polling mechanism.

      • 08/11/2013 at 19:24 | #42

        Right click and run as Admin works like a charm, thanks

        aer

  16. 02/10/2012 at 10:02 | #43

    Thank you Geert for your tutorial. I’m a internship student and having assignments in EA. I find your blog is helpful. I will write this blog in my reference.

  17. Khalil
    31/10/2012 at 15:52 | #44

    Hello greet , thank you for this interesting tutorial , but i have some problems and i wish u can help me with it . .
    First i follow all ur instruction and i have created the add-in , the problem is that i need to distribute it . when i access my bin\Rlease file in my VS2010 project “it is empty” , i tried to build the solution and copy bin\Debug files into some place and when i run this inside my cmd “e:\\….\EA Add-In\dis\regasm KJaddin.dll/codebase ” i get this error
    ( RegAsm : error RA0000 : unable to locate input assemly ‘KJaddin.dll/codebase’ or one of it’s dependencies ) , thought that i have copied the RegASm.exe from inside the framework file . . so i need ur help
    Thanks in advance

    • 31/10/2012 at 18:35 | #45

      Hi Klahil

      I think you need a space between the path to your dll and the option /codebase.

      Geert

  18. Khalil
    25/11/2012 at 20:47 | #46

    Thank u so much Greet , i found the error and its fixed , now (thanks to u ) i can deploy my Add-in (using the other article ), but i have some problems with my new Add-In project and i wish that u can help me :

    1. if i use a database in my Add-In project i have this error (( An attempt to attach an auto-named database for C:\Program Files\Sparx Systems\EA\DataBase\DBMetric.mdf failed. A database with the same name exists, or specified file cannot be opened or its located on UNC share.)) i have tried a dozens of article for this error but no chance to fix it.

    2. if i use a crystal report in the Add-In project ,once i push the button that trigger the report then EA (v7.5) crach which show me a dialog of Debug or Close button.

    so is there any thing u can do i really appreciate it.
    thanx in advance .

  19. Khalil
    26/11/2012 at 09:58 | #48

    thank u Greet for ur patience , this question (on stackover flow is Mine , none of the answers solve my problem ) for now ; let us leave the Database issue , how can i send u a small project (Add-in) that print a report using crystal reports ? i will make a simple one and send it to u so u can check my broken car ^_^ , again i’m sorry if i’m bothering u . .
    Thanks in advance

    • 26/11/2012 at 11:42 | #49

      With “more debugging/troubleshooting yourself” I didn’t mean “send the whole lot to Geert and let him figure it out”.

      I’m happy to help, but I’m not willing to do your job for you. (unless you pay me)

  20. Khalil
    26/11/2012 at 11:45 | #50

    Fair enough , i’m sorry
    thanks for every thing .

  21. Ondřej Kála
    07/12/2012 at 12:31 | #51

    Hi, great tutorial, I have a small question – how do I get the location of currently opened .eap file from my Add-In? Thx for help.

    • 07/12/2012 at 12:39 | #52

      Repository.Connectionstring

      • Ondřej Kála
        07/12/2012 at 18:53 | #53

        Thx and how do I get the location of the EA folder? (C:\Program Files (x86)\Sparx Systems\EA normally)

      • 08/12/2012 at 06:01 | #54

        There are a few different ways to do that. Try googling for something like “location of running assembly in c#”.
        Some of these options will return the path of your dll, others will return the path of ea.exe, but I don’t remember which does what.

  22. 06/01/2013 at 12:25 | #55

    Geert ! Great article. Have you thought about writing add-in to integrate balsamiq mockups with EA? That would be an awesome tool.

    • 07/01/2013 at 08:28 | #56

      Hmm, interesting idea. I can think of a couple more people that would be interested in something like that. I’ll think about it.

  23. Ondřej Kála
    05/05/2013 at 12:52 | #57

    Hi, what installer program can I use? Which one can you set to run the regasm.exe?

  24. Fabio Scussel
    14/05/2013 at 04:44 | #59

    Thanks a lot! Great article!!!

  25. Samir
    17/05/2013 at 15:45 | #60

    Hey, I was wondering if anyone managed to develop and add an addin to EA under Linux Ubuntu. I followed the instructions above but when I start EA and go to “Extensions –> Manage Add-Ins..”, I see my Add-in with the an “Error-Missing” status. It seems that EA can’t locate “MyAddinClass.cs” for some reason. I’m running EA under Wine and I am using Mono for development. Would be really cool if I can make it work from within Ubuntu. Thanks in advance.

    Samir

    • 21/05/2013 at 07:23 | #61

      Samir,

      I don’t think there’s a reason why it wouldn’t work on linux.
      You probably either have misspelled something in the add-in registry key, or you have an issue registering the dll in COM.
      Have you tried it using regasm.exe?

      Geert

      • Samir
        23/05/2013 at 11:29 | #62

        Hi Geert,

        thanks for your reply. You are right it’s definitely a problem with registering the COM dll. It’s also a problem that’s definitely solvable but unfortunately, I don’t have lots of time to solve it so I started working on a windows environment using VS as an IDE. I now need to dynamically create an Enterprise Architect “Element” of type “Note” and add it to a “DiagramObject” (any of the nodes). Can you maybe help me with how I can do that? It’s my first EA addin :) Thanks in advance.

        Samir

  26. Samir
    23/05/2013 at 11:35 | #63

    To make my question more specific. How can I dynamically attach a note to one of the nodes in the diagram (DiagramObject). From within EA, I can right-click then select “New Element” –> “Attach note”. How can I do the same thing from within my Add-in C# code?

    Samir

    • 23/05/2013 at 12:16 | #64

      To make a new note you have to use AddNew() on the diagram owners Elements collection.
      Then you have to add a new DiagramObject for the note (AddNew on the Diagram.DiagramObjects collection) and then you have to add a link between your new Note and whatever element is represented by the DiagramObject you want to link it to. So you do a AddNew() on the Notes Connectors collection and set the target element ID to the ElementID of the DiagramObject.
      There are some examples in the help file, and in your installation directory that might be of help.

      • Samir
        23/05/2013 at 12:58 | #65

        I tried:
        diagram.DiagramObjects.AddNew(“New Activity”, “Activity”);
        MessageBox.Show(“Count: ” + diagram.DiagramObjects.Count);

        but it didn’t work unfortunately. I can’t see my “New Activity” in the project explorer or in the model editor either. The count of diagram objects before and after my AddNew() invocation is the same. I am probably missing a step. Do u know what it is, maybe? Thanks

        Samir

      • 23/05/2013 at 13:02 | #66

        If you are not going to read my replies I don’t know why I should bother.

  27. Samir
    23/05/2013 at 13:07 | #67

    I read your whole comment but as a progressive implementation, I wanted to add a simple activity and check if it is added and then go on from there. I also checked the EA help but I couldn’t find example use cases. Why do u think I didn’t read your comment?

    • 23/05/2013 at 13:14 | #68

      Because the first thing I said was to create a new element in the diagram owners Elements collection.
      You have to have an element first before you can add a DiagramObject.
      So read it again and try these steps in the correct order.
      And of course you should always Update() otherwise nothing gets saved. (and you don’t see any results)

      • Samir
        23/05/2013 at 14:06 | #69

        oh sorry, I thought u meant to do that only for Notes. One can misunderstand that I guess, especially when he’s new with all of this. Here’s basically what it is now:
        selectedPackage.Elements.AddNew(“Activity”, “Activity”);
        diagram.DiagramObjects.AddNew(“Activity”, “Activity”);

        // Followed by some refreshs and reloads

        I see the created element in the project explorer but I can’t seem to add it to the diagram. Is my invocation of AddNew() on DiagramObjects called incorrectly?
        Right now, it’s as if I only added the element by right clicking on the owner package in the project explorer

  28. Samir
    23/05/2013 at 14:23 | #70

    Forgot to mention that I called update() on the DiagramObject of course and refreshed diagram.DiagramObjects. The count is incremented but the object is not visually present in the diagram (I made all required refreshs and reloads)

  29. Samir
    23/05/2013 at 14:54 | #71

    I found the solution. I just needed to assign the diagram element id to be the same as the ID of its element instance:
    newDiagramObject.ElementID = element.ElementID;

    Thanks again, Geert.

    best regards,
    Samir

  30. Amine
    18/06/2013 at 16:05 | #72

    Hello geert,
    I tried to do all what it’s said in the tutorial and the build is succeeded , but when I try to run it they said : “A project with an output type of class library cannot be started directly. In order to debug this project, add an executable project to this solution which references the librar project. Set the executable project as the startup project.”
    Can you please tell me what it’s wrong with that.
    Thank’s.

    • 18/06/2013 at 16:17 | #73

      Exactly, as said you cannot run an add-in seperately.
      You just start EA and EA runs the add-in for you.

      What I often do to test my add-ins is use a tester application, see

      Geert

  31. Amine
    19/06/2013 at 08:47 | #74

    Hello again,
    when I start EA and go to Manage Add-ins they told me :”there are no items to show in this view.”. Do you you know what is the problem with that ?

    Thanks

  32. Amine
    19/06/2013 at 10:04 | #75

    Hello,
    It finnaly works, it was a problem of key, thank’s for helping.
    I have another question: Do you know if there is and add-in which extract data from diagram,for example I have a deployment diagram and I want to extract all the class with there attributes and generate all this in an output file . Do you have any idea for this ?

    thanks again geert.

    • 19/06/2013 at 12:50 | #76

      Have you tried the RTF reports? I think they work on diagram basis. If that doesn’t do what you need you might want to try EADocx http://www.eadocx.com/

      I I needed something like that I would probably just write it myself. Should be no more then a day of work.

  33. bilanovi9c0
    25/06/2013 at 14:30 | #77

    Hi,

    first of all great tutorial. One help if u know because i can’t find anything else about using EA with c#.
    I’m trying to import and export project into XMI trough code with ExportPackageXMI() and ImportPackageXMI() methods. Export is working, but import is giving me errors.
    First one is “DAO.Recordset [3021] No current record”, second “sorry this feature is disabled in the re-distributable version of enterprise architect”.
    And it would be lovely if u had any literature to share,

    Thanks

  34. 17/07/2013 at 13:28 | #79

    Thanks for making thi great tutorial. I am currantly working on an add-in to help synchronize data between EA and Microsoft Team Foundation Server. In this addin I would like to respond to elements being changed in the project browser tree. I thought I would respond to the “EA_OnNotifyContextItemModified” event but I can’t seem to get that to work. Do you have any ideas on how to synchronise elements I use in my addin with their corrosponding elements in the EA project browser tree?

    • 17/07/2013 at 13:52 | #80

      What exactly isn’t working with the EA_OnNotifyContextItemModified? I have no information that that operation should be working.

      I have lots of ideas, but which ones are relevant depends on your requirements.
      - Is your integration one-way, or two-way
      - Do yo need a “batch” type of processing or some kind of continues integration?

      Geert

  35. 17/07/2013 at 15:14 | #81

    I have this code in the add-in baseclass:

    public void EA_OnNotifyContextItemModified(EA.Repository Repository, string GUID, EA.ObjectType ot)
    {
    if (ot == EA.ObjectType.otElement)
    {
    EA.Element element = Repository.GetElementByGuid(GUID);

    }
    }

    I have a breakpoint on the first IF statement but the program never gets to that point no matter what I do in the project browser. I made a list of items that will be synchronized to TFS. When the user edits an element in th EA tree while the synchronization screen is filled I want this screen to reflect the changes the user made in EA tree.

    • 17/07/2013 at 17:15 | #82

      I just tested the operation with this code:
      public override void EA_OnNotifyContextItemModified(EA.Repository Repository, string GUID, EA.ObjectType ot)
      {
      MessageBox.Show(“OnNotifyContextItemModified works!”);
      }
      And it works for me. I tested it on v 10.0.1000.
      This snippet of code is part of my MyAddin example addin that uses the EA Addin Base class as parent: https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/master/EAAddinFramework/EAAddinBase.cs

      • 18/07/2013 at 08:34 | #83

        I am using the myaddin example and the framework and baseclass everything is tested on EA V10.0.1006 Still if I change the notes or the name of a usecase there is no event even after creating modifying and deleting an item in the tree still no event. Really frustrating, I’m going to drop this now and I’ll just tell my users they can’t change stuff or just reload everything in the sync list….

      • 18/07/2013 at 08:39 | #84

        That is indeed weird. Maybe a bug has slipped in the in between v10.0.1000 and v10.0.1006?
        Have you tried with v10.0.1008?
        If you still have issues with that I would contact sparx support. They are usually pretty helpful.

  36. 18/07/2013 at 12:46 | #85

    I will focus on finishing the product first. Unfortunately my company does not allow me to quickly install new versions of software. The bug could also have something to do with our server configuration. When I have more time I will try to look into solving the problem. Anyway, thanks for the help and suggestions, much appreciated! :)

  37. Khalil
    19/07/2013 at 20:49 | #86

    hello Greet , how are u doing , thanks for this great article , i have just finish an add-in for EA 7.5 which measure object oriented design metrics for class diagram . if u are interested do not hesitate to replay ^_^ . Thanks

  38. Phil
    29/08/2013 at 09:04 | #87

    Hi

    I created an add in for EA and this has worked successfully for more than 1 year in Windows 7. I now have a new laptop, using Windows 8. Visual Studio 2008 installed. EA Installed. EA invokes my add in, but my first call to Interop.EA, returns a 80040154 error. What must I do to fix this ? Thanks and Regards

    • 29/08/2013 at 10:30 | #88

      Just like that I can’t really say what’s wrong.
      The error indicates that there is a problem with the COM registration of one of the elements you are using.

      Have you tried to delelete and re-add the reference to the interop.EA dll?

      If you send me part of the code, and the line where it gives you the error I might be able to say more.

      Geert

      • Phil
        29/08/2013 at 10:52 | #89

        Hi Geert

        Thank you for coming back to me so quickly. In unregistered the reference, re-booted, registered the reference again, and re-compiled my project.

        I still get the error!

        Here is where it happens in my code :

        MessageBox.Show(“Opening EA”);
        EA.Project projectinterface = new Project();
        projectinterface = DocumenterClass.Rep.GetProjectInterface();

        As soon as I acknowledge the messagebox, the error comes up.

        However, as stated before, no such error on my Windows 7 machine!

        I will try re-installing EA.

        Regards

        Phil

      • 29/08/2013 at 11:33 | #90

        Phil,

        I don’t think “new Project()” works, and it doesn’t seem necessary at all. EA.Project projectinterface = DocumenterClass.Rep.GetProjectInterface(); should be enough (if DocumenterClass.Rep is a valid EA.Repository object).

        Geert

      • Phil
        29/08/2013 at 11:33 | #91

        Success!! Would you believe it ? I re-installed EA, and everything is perfect! It must be because it was first installed by a technician, using a different Windows profile!

  39. Phil
    29/08/2013 at 12:01 | #92

    Thank you for your help!
    Regards

    Phil

  40. Samir
    27/09/2013 at 14:02 | #94

    Hi,

    I was wondering if it’s possible to acquire the DiagramObject (if present) corresponding to an element that I have. I tried simple casting for an element that corresponds to a node that I can see in my diagram but it didn’t work. Is the only approach to loop on all DiagramObjects and compare element IDs to DiagramObject IDs until I find it? I hope there’s a smarter solution.

    Thanks in advance,
    Samir

    • 27/09/2013 at 14:15 | #95

      Hi Samir,

      That is indeed to only solution. I’m not sure why that isn’t smart, and what you were expecting instead though.

      Geert

  41. Samir
    27/09/2013 at 20:15 | #96

    Hi Geert,

    thanks for your reply. That was merely a humble opinion of mine. It is possible I am wrong. However, I thought that it might have been possible that the api stores the Element-DiagramObject pairs in a dictionary, for instance, so that the user can access them later easily (through a function that maybe I was missing, hence my question). That’s why I thought maybe it’s a stupid idea of mine but feels great that you don’t think it’s a stupid approach. I implemented it this way and it’s working fine :) Thanks again.

    Samir

  42. bilanovic90
    29/10/2013 at 10:49 | #97

    Hi,

    do you know how can i call option from menuBar Diagram->Layout Diagram?

    bilanovic90

  43. 08/12/2013 at 02:33 | #98

    Hi,
    We are able to successfully build the project as you instructed but still can not see the addin button in the enterprise architect. Could you please resolve the issue or share any related documentatiob. Here in following link share the project. We tested the code in VS-2013. Thank you so much.
    Project-https://www.dropbox.com/s/kw89xbt7nf24n7l/MyAddin.zip

    • 09/12/2013 at 19:42 | #99

      Are you sure you created the correct entry in the registry?

      • Frank
        10/12/2013 at 19:37 | #100

        Hi,

        I also run first into the problem, that my addin has not been loaded proberly by EA. But if I copy the addin to the directory where the EA.exe is located it works. Ok if you are developing to copy your addin might be a nightmare but this is even better then nothing. But still the remaining question how does EA now from where to load the addin if it is not in the EA directory. Is there a kind of EA PATH somewhere? Maybe geert can answer that.

      • 11/12/2013 at 08:05 | #101

        I thought I already explained that in this article.
        EA get the name (including the namespace) of the class it needs to load from the registry entry in [HKEY_CURRENT_USER\Software\Sparx Systems\EAAddins] and then asks the COM registry system for the location of the dll (codebase).
        If it can’t find it that way it will also try to load the dll from its own location.
        So if it only works when placing the dll in the same directory as EA.exe then you haven’t successfully registered your dll in COM.

      • 11/12/2013 at 12:22 | #102

        Yes, I fixed the problem. The issue I had in the registry key under this location[HKEY_CURRENT_USER\Software\Sparx Systems\EAAddins]
        I just add registry key like this : project name followed by class name and it works. Thanks.

  44. Frank
    11/12/2013 at 09:10 | #103

    Hi Geert,

    thanks for your answer. It seems that I missunderstood your earlier explanations. Based on your current answer I rechecked my complete VS Setup and found out that for what ever reason VS requests to run as admin in order to proper register the dll in COM. So if I run VS as Admin all works as you described earlier. It’s always the same, the stupid guy is in front of the machine. thx Frank

  45. 15/01/2014 at 09:47 | #104

    Sparx Add-in “Error – Missing”: There is an error in the CS_AddinTaggedCSV tutorial I downloaded here (http://www.sparxsystems.com/resources/developers/autint.html). You need to edit the .reg script and set the value to CS_AddinTaggedCSV.Main

  1. 31/01/2011 at 10:59 | #1
  2. 08/02/2011 at 05:01 | #2
  3. 15/02/2011 at 04:52 | #3
  4. 16/02/2011 at 02:55 | #4
  5. 23/02/2011 at 04:48 | #5
  6. 28/02/2011 at 08:13 | #6
  7. 08/01/2014 at 05:54 | #7

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 213 other followers

%d bloggers like this: