Author Topic: C# equivalent to GetObject(, "EA.App")  (Read 11637 times)

TheMintRubber

  • EA Novice
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
C# equivalent to GetObject(, "EA.App")
« on: June 15, 2017, 09:53:05 pm »
Hi,

I am trying to open a diagram in an already opened instance of Enterprise Architect.

I've found this code in vb, in here, that gets a reference to a currently running instance of Enterprise Architect:

Dim App as EA.App
Set App = GetObject(,"EA.App")
MsgBox App.Repository.Models.Count

Does anyone have the equivalent code in C#?

I've already tryied, and failed, to use:

System.Runtime.InteropServices.Marshal.GetActiveObject("EA.App");

or

var type = System.Type.GetTypeFromProgID("EA.App");
var app = (EA.App)System.Activator.CreateInstance(type);

Both of these return a new instance instead of the existing one.

Thanks,
Doru Foaltin

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #1 on: June 15, 2017, 10:35:14 pm »
Don't know if it helps, but C++ looks like
Code: [Select]
CLSID clsid;
CLSIDFromProgID(L"EA.App", &clsid);
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;
HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk); if(SUCCEEDED(hr)) {
 hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);
}

q.

TheMintRubber

  • EA Novice
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #2 on: June 15, 2017, 10:44:02 pm »
Quote
Don't know if it helps, but C++ looks like

CLSID clsid;
CLSIDFromProgID(L"EA.App", &clsid);
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;
HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk); if(SUCCEEDED(hr)) {
 hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);
}

Hi qwerty,

I've seen the c++ code in your book. I guess I can make a wrapper for that c++ code to be used in C#, but I was hoping for no workarounds, and just get a proper C# version.

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #3 on: June 15, 2017, 11:20:06 pm »
Have a look into Geert's works on github. I don't know if he using that somewhere, but at least he's a sharp guy ;-)

q.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13387
  • Karma: +566/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: C# equivalent to GetObject(, "EA.App")
« Reply #4 on: June 15, 2017, 11:20:50 pm »
Code: [Select]
using System.Runtime.InteropServices;
object obj = Marshal.GetActiveObject("EA.App");

Geert

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile

TheMintRubber

  • EA Novice
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #6 on: June 16, 2017, 12:14:43 am »
Quote
Hehe. Was about to point to http://sparxsystems.com/forums/smf/index.php/topic,30896.msg224335.html#msg224335

I've found the problem from @qwerty's answer:

I had a background EA Process that didn't had any Repository loaded.

Thank you all for the help.

Is there any way to get an instance of the EA.App class for all EA Processes? Or I am stuck in handling just the first opened EA instance?

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile

Helmut Ortmann

  • EA User
  • **
  • Posts: 970
  • Karma: +42/-1
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #8 on: June 19, 2017, 01:01:11 am »
Hi,

if you develop C# according to EA Hybrid Scripting you can use the 'SparxSystems.Repository.dll'.

'SparxSystems.Repository.dll' has the possibility to load the EA Model according to the process-id of the EA Instance in a C# environment.

At http://community.sparxsystems.com/community-resources/1065-use-c-java-for-your-vb-script
you see an Example for C#. In that case to call C# from VBscript in EA and get the correct Repository in C#.

Kind regards,

Helmut
Coaching, Training, Workshop (Addins: hoTools, Search&Replace, LineStyle)

TheMintRubber

  • EA Novice
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #9 on: June 19, 2017, 07:18:24 pm »
Hi,


@Helmut Ortmann: That is available only in EA 13, I have to target EA 12, so I can't use it.

Using qwerty's answer, I've made the following implementation:

Code: [Select]
   

        [DllImport("ole32.dll")]
        public static extern int GetRunningObjectTable(int reserved, out UCOMIRunningObjectTable prot);

        [DllImport("ole32.dll")]
        public static extern int CreateBindCtx(int reserved, out UCOMIBindCtx ppbc);

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        private const int SW_RESTORE = 9;
        [DllImport("user32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll")]
        private static extern bool IsIconic(IntPtr hWnd);

        public static List<EAAppInstance> GetEAInstances()
        {
            List<EAAppInstance> result = new List<EAAppInstance>();

            Hashtable runningObjects = GetRunningObjectTable();

            IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
            while (rotEnumerator.MoveNext())
            {
                string candidateName = (string)rotEnumerator.Key;

                if (!candidateName.ToUpper().Contains("EA"))
                    continue;

                EA.App eaApplication = rotEnumerator.Value as EA.App;

                if (eaApplication == null)
                    continue;

                // Remember the process Id so we can Show that window to the user
                int processId = int.Parse(candidateName.Split(':')[1]);

                result.Add(new EAAppInstance(eaApplication, processId));
            }

            return result;
        }

        [STAThread]
        public static Hashtable GetRunningObjectTable()
        {
            Hashtable result = new Hashtable();

            int numFetched;
            UCOMIRunningObjectTable runningObjectTable;
            UCOMIEnumMoniker monikerEnumerator;
            UCOMIMoniker[] monikers = new UCOMIMoniker[1];

            GetRunningObjectTable(0, out runningObjectTable);
            runningObjectTable.EnumRunning(out monikerEnumerator);
            monikerEnumerator.Reset();

            while (monikerEnumerator.Next(1, monikers, out numFetched) == 0)
            {
                UCOMIBindCtx ctx;
                CreateBindCtx(0, out ctx);

                string runningObjectName;
                monikers[0].GetDisplayName(ctx, null, out runningObjectName);

                object runningObjectVal;
                runningObjectTable.GetObject(monikers[0], out runningObjectVal);

                result[runningObjectName] = runningObjectVal;
            }

            return result;
        }

Thanks to all for your replies,
Doru.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13387
  • Karma: +566/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: C# equivalent to GetObject(, "EA.App")
« Reply #10 on: June 20, 2017, 04:07:32 pm »
Thank you for posting your code.
I'm sure I'll be needing this one day  :)

Geert

Helmut Ortmann

  • EA User
  • **
  • Posts: 970
  • Karma: +42/-1
    • View Profile
Re: C# equivalent to GetObject(, "EA.App")
« Reply #11 on: June 21, 2017, 07:06:07 pm »
Hi TheMintRubber,

I checked your Code. It works as expected if I add the below code.

Code: [Select]
public class EAAppInstance
{
public EA.App EaApp { get; }
public int ProcessId { get; }
public EAAppInstance(EA.App eaApp, int processId)
{
EaApp = eaApp;
ProcessId = processId;
}

}

I think the effect is similar to the EA DLL 'SparxSystems.Repository.dll'. This SPARX DLL get's the repository from the passed EA process id and was first released with EA 13. I think this DLL also works for older EA releases, but I'm not sure about.

Thanks a lot for sharing your code. It also gives me an inside how such things work.

Kind regards,

Helmut

Coaching, Training, Workshop (Addins: hoTools, Search&Replace, LineStyle)