Sparx Systems Forum

Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: mateiacd on October 03, 2016, 06:43:02 pm

Title: EA process remains after releasing COM interface in C++, version 12.1.0.1229
Post by: mateiacd on October 03, 2016, 06:43:02 pm
Hello,

I am using Enterprise Architect 12.1.0.1229

I would like to use the Automation API in Visual C++ 2010. I created a simple Win32 console project.

After trying a simple code like below for a console application, releasing the COM pointer I still see an EA process left running in the Windows task manager.

I am only trying to launch the Enterprise Architect COM server using the EA.App ProgID

HKEY_CLASSES_ROOT\EA.App\CLSID
    {3A9E4F92-8D27-495B-8B22-1D702B3F0C83}

I succeed, but  even after exiting the console application I see the EA.exe *32 in the list of processes

Can anybody help ? Thanks !
Code: [Select]
CoInitialize(NULL);

CLSID clsid;
OLECHAR wb[] = L"EA.App";
CLSIDFromProgID(wb, &clsid);


IDispatch* pDispatch;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pDispatch);
if (FAILED(hr))
{
MessageBox(NULL,_T("CoCreateInstance failed"),_T("Enterprise Architect"),MB_OK);
return;
}

pDispatch->Release();
CoUninitialize();

I also tried this variation with the same result. After the application closes, I still have the problem of getting rid of the EA.exe *32 process
Code: [Select]
IUnknown* pUnknown;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);
if (FAILED(hr))
{
    MessageBox(NULL,_T("CoCreateInstance failed"),_T("Enterprise Architect"),MB_OK);
    return;
}


IDispatch* pDispatch;

cout << "Client: Calling QueryInterface() for IDispatch on " << pUnknown << endl;
hr = pUnknown->QueryInterface(IID_IDispatch, (void**)&pDispatch);

if (FAILED(hr))
{
MessageBox(NULL,_T("QueryInterface failed"),_T("Enterprise Architect"),MB_OK);
pUnknown->Release();
return;
}

pDispatch->Release();
pUnknown->Release();


P.S. Can I attach files to this post ? I would like to attach some screen captures.
Title: Re: EA process remains after releasing COM interface in C++
Post by: Geert Bellekens on October 03, 2016, 07:18:39 pm
there is a code tag that makes reading code a bit easier on the eye.
If you want to attach images you have to upload them to a public image server such as imgur.com and then include them in an img tag.

Have you tried the Repository.Exit function?

Geert
Title: Re: EA process remains after releasing COM interface in C++
Post by: mateiacd on October 03, 2016, 07:41:25 pm
In C++ I see no such functionality like Repository.Exit()
Can you explain how ? Thank you.
Title: Re: EA process remains after releasing COM interface in C++
Post by: Geert Bellekens on October 03, 2016, 07:44:09 pm
See http://sparxsystems.com/enterprise_architect_user_guide/12.1/automation_and_scripting/repository3.html (http://sparxsystems.com/enterprise_architect_user_guide/12.1/automation_and_scripting/repository3.html)
The main API object EA.Repository has an operation Exit() that should kill the process completely.

Geert
Title: Re: EA process remains after releasing COM interface in C++
Post by: Uffe on October 03, 2016, 07:44:41 pm
Repository.Exit() is contraindicated in this situation, as the API documentation lists is explicitly for use from .NET.

But it appears as if you're using EA.App rather than EA.Repository. Why is that?

The normal way to use the EA API from a stand-alone application is to create an instance of EA.Repository (http://www.sparxsystems.com/enterprise_architect_user_guide/12.1/automation_and_scripting/repository3.html), call OpenFile() to connect to a repository, and then when you're finished call CloseFile().

The undocumented, or poorly documented, EA.App (http://www.sparxsystems.com/enterprise_architect_user_guide/12.1/automation_and_scripting/app.html) is a reference to a running instance of the client, which is not typically what you want when writing a stand-alone application. If you want your code to run within the context of an EA client, the normal way is to create an Add-In (http://www.sparxsystems.com/enterprise_architect_user_guide/12.1/automation_and_scripting/addins_2.html) instead.

HTH,


/Uffe
Title: Re: EA process remains after releasing COM interface in C++,version 12.1.0.1229
Post by: mateiacd on October 03, 2016, 08:03:33 pm
All right, I tried also EA.Repository

HKEY_CLASSES_ROOT\EA.Repository\CLSID
    {67F4E0FA-46A7-4255-B084-69A9433D08C3}

and still the instance of EA.exe *32 appears in Task Manager after closing my application.

However a colleague using Enterprise Architect version 10.0.1006 does not have this problem !

On his computer, my code works as expected, everything is cleaned up properly...

So it appears to be a case only for me using Enterprise Architect version 12.1.0.1229


Title: Re: EA process remains after releasing COM interface in C++, version 12.1.0.1229
Post by: mateiacd on October 04, 2016, 02:11:51 am
Thank you very much Uffe for pointing me to use EA.Repository as a ProgID!!!

It seems that  EA.exe *32 is closed properly in Task Manager only if we explicitly call all three methods below:
OpenFile
CloseFile
ExitFile

Here is the relevant code, I hope it will be useful for other programmers  working with C++.

Code: [Select]
void Test1()
{
CLSID clsid;
CLSIDFromProgID(L"EA.Repository", &clsid);

IRepository* pRepository;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDualRepository, (void**)&pRepository);
if (FAILED(hr))
{
MessageBox(NULL,_T("CoCreateInstance failed"),_T("Testing app"),MB_OK);
return;
}

_variant_t fileName(_T("D:\\Temp\\getting-started.eap"));

pRepository->OpenFile(fileName);
_variant_t pg = pRepository->GetProjectGUID();
pRepository->CloseFile();
pRepository->Exit();

pRepository->Release();
}


and the other relevant code:

Code: [Select]
#include "stdafx.h"
#include <comdef.h>
#include <iostream>

using namespace std;

#import "C:\\Program Files (x86)\\Sparx Systems\\EA\\EA.tlb" no_namespace named_guids

void Test1();

int _tmain(int argc, _TCHAR* argv[])
{
 HRESULT hr = CoInitialize(NULL);
 if(FAILED(hr))
 {
MessageBox(NULL,_T("CoInitialize failed"),_T("Testing app"),MB_OK);
cout << " failed" << endl;
 }

 Test1();

 CoUninitialize();

 MessageBox(NULL,_T("Finish"),_T("Testing app"),MB_OK);
 return 0;

}