2004. január 23., péntek

Registering an ActiveX for its class


Problem/Question/Abstract:

How getting the IUnknown reference on a specific COM object's instance created by an application ?

Answer:

The RegisterActiveObject function -from the Win32 API- can register an object by passing its IUnknown reference and its CLSID to make it the active object for its CLSID.
Registration causes the object to be listed in OLE's running object table, a globally accessible lookup table that keeps track of the objects that are currently running on your computer.
An application can then create an OLE automation object for example, register it as the active object at startup.
Other application can have access to this particular instance by getting a IDispatch reference with the Delphi's GetActiveOleObject using its progID.

I've placed the registration mecanism in the TActiveObject class showed bellow and you can download the demo applications.

unit ActiveObject;

// Written by Bertrand Goetzmann (http://www.object-everywhere.com)
// Keywords : RegisterActiveObject, CoLockObjectExternal, RevokeActiveObject, CoDisconnectObject, GetActiveOleObject, GetActiveObject

interface

type
  TActiveObject = class
  private
    FUnk: IInterface;
    FRegister: Integer;
  public
    constructor Create(Unk: IInterface; const clsid: TGUID); overload;
    constructor Create(Unk: IInterface; const ProgId: string); overload;
    destructor Destroy; override;
  end;

implementation

uses ActiveX, ComObj;

{ TActiveObject }

constructor TActiveObject.Create(Unk: IInterface; const clsid: TGUID);
begin
  inherited Create;
  FUnk := Unk;
  OleCheck(RegisterActiveObject(FUnk, clsid, ACTIVEOBJECT_WEAK, FRegister));
  OleCheck(CoLockObjectExternal(FUnk, True, True));
end;

constructor TActiveObject.Create(Unk: IInterface; const ProgId: string);
begin
  Create(Unk, ProgIDToClassID(ProgId));
end;

destructor TActiveObject.Destroy;
begin
  OleCheck(CoLockObjectExternal(FUnk, False, True));
  OleCheck(RevokeActiveObject(FRegister, nil));
  OleCheck(CoDisconnectObject(FUnk, 0));
  inherited;
end;

end.

In the demo applications, OleObject.dll is the implementation of the OLE automation object with "OleObject.Test" as progId and supporting the ITest interface. This interface has a single property named Message : you can read or write a simple string of characters.
The AppTest.exe creates an instance of this OLE automation object and register it with an instance of TActiveObject. When the applicatino shut down, the registration of the active objet is revoked.
Start several instances of ClientTest. ClientTest gets the IDispatch reference, via a Variant variable, on the active object by using a call of GetActiveOleObject('OleObject.Test'), to set or get the Message property value.

I think it is a powerful way to make applications more collaborative.


Component Download: http://perso.worldonline.fr/objecteverywhere/ActiveObject.zip

Nincsenek megjegyzések:

Megjegyzés küldése