Link to home
Start Free TrialLog in
Avatar of jpcs
jpcs

asked on

Create, use and destroy ActiveX Connection

Hello there,

I've got a problem that is now becoming very annoying :

I have an ActiveX that I must use WITHOUT TYPE LIBRARIES, so I must use CreateOleObject, OleProcedure, OleFunction, Exec, etc. However, the problem is when I try to destroy the connection, it doesn't really destroy it, because I simply cannot delete/update the ActiveX until the host application terminates.

Code:

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    vTest : Variant;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses ComObj;

procedure TForm1.Button1Click(Sender: TObject);
begin
   vTest := CreateOleObject ('EnterAProgID.Here');
   vTest := Unassigned;
end;


Example for an activex availlable:
download one ActiveX component from hxxp://wxw.chilkatsoft.com (i've tried the xml-activex).

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    vTest : Variant;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses ComObj;

procedure TForm1.Button1Click(Sender: TObject);
begin
   // http://www.chilkatsoft.com/xml-activex.asp
   vTest := CreateOleObject ('ChilkatXml.ChilkatXml.1');
   vTest := Unassigned;
end;


In VB, the result is the same:

Private vTest As Variant

Private Sub Command1_Click()
    Set vTest = CreateObject("ChilkatXml.ChilkatXml.1")
    Set vTest = Nothing
End Sub



Thanks for all the help you can give me.

Joao
Avatar of BigRat
BigRat
Flag of France image

This is because the DLL contains a factory object which makes the control and this factory object resides in memory once the Dll has been loaded. The only way to replace a DLL from which a control has been loaded is to terminate all applications using the DLL or controls contained therein.
ASKER CERTIFIED SOLUTION
Avatar of Russell Libby
Russell Libby
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jpcs
jpcs

ASKER

Hello Russel,


Thanks very much for your answer!

It fixed my problem.

Can you just help on one thing?

How can I call this function in C++ builder 5?

I simply cannot find it.


Thanks.
Your kidding, right? <g> I thought this was the Delphi TA? Seriously though, its declared in objbase.h, example given below:

Russell

//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#include <objbase.h>

#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

      CoFreeUnusedLibraries();
 
}
//---------------------------------------------------------------------------
Avatar of jpcs

ASKER

Please ignore my last comment.

I've found out everything.


You have just solved a problem I have been having for the last 2 years...


I cannot thank you enough!!!


Joao
You are very welcome, glad to assist

Russell

Avatar of jpcs

ASKER

Looks like my comment wasn't on time :)

Yes, this is a delphi TA (I just used it, since the languages share the VCL and there are LOTS of more users).

I usually manage to make the changes on my own, however, in this issue, I was looking for the method in ActiveX.hpp... I've found it later just after I wrote the comment.

Thanks
Avatar of jpcs

ASKER

Russel,

I don't know if you know anything about this, but I can try...

This code works fine with some of my custom ActiveXs, except with the ones created using .net!


I suppose the problem is with a missing DllCanUnloadNow api. I've tried to find tips in the net, but with no luck!

Can you assist me with this?


Thanks.

Joao

I doubt if the api call is missing (as it is required along with DllGetClassObject), but there are a few notes from MS that go along with the CoFreeUnusedLibraries call:

<quote>

SYMPTOMS
Dynamic-link libraries (DLLs) that are not in use may not be unloaded from the process space after calling the CoFreeUnusedLibraries function.
 Back to the top

CAUSE
This problem occurs when the application still has references to the components in the DLL, or when the application releases all the references to a DLL but does not make a subsequent call to CoFreeUnusedLibraries.
 Back to the top

RESOLUTION
CoFreeUnusedLibraries does not immediately release DLLs that have no active object. There is a ten minute delay for multithreaded apartments (MTAs) and neutral apartments (NAs). For single-threaded apartments (STAs), there is no delay. The ten minute delay for CoFreeUnusedLibraries is to avoid multithread race conditions caused by unloading a component DLL.

To work around the problem, make a second call to CoFreeUnusedLibraries after ten minutes, or make periodic calls to CoFreeUnusedLibraries. For applications that run for long periods, such as Windows NT Service applications, calling CoFreeUnusedLibraries periodically ensures that DLLs that are not being used are unloaded.

Another workaround is to call CoUninitialize, which closes the COM library and releases all resources used by the current thread.
 Back to the top

STATUS
This behavior is by design.

---
as to how .NET (mscoree.dll) play into this, I can't really say


Russell

Avatar of jpcs

ASKER

Thanks for your help Russell,

I've just posted a new question, but in the c# area. Hope to get the solution.


Regards,

Joao