简体   繁体   中英

COM Object and different versions of DLL

I'm very new to DLL objects and I search everywhere and can't find the right answer. I doing little addon to Microsoft RMS, it automatically calls function Process from my dll with IDispach parameter passing current session details.

I'm using interface from QSRules.dll (Components > Import > Component > Typed Library ... Add To Project). It creates TLB file with all references etc.

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
begin

  CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Name', (Session as SessionClass).Cashier.Name );
  CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Number', (Session as SessionClass).Cashier.Number );

end;

That works perfectly with software version 2.01 but when trying to use the same function on version 2.02 it crash with "Interface not supported". The QSRules.dll has updated version and GUID's for all classes are different.

I tried that with fallowing code:

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
begin

  if Supports(Session, QSRules_TLB_2_0_0_151.SessionClass) then
    Begin
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Name', (Session as QSRules_TLB_2_0_0_151.SessionClass).Cashier.Name );
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Number', (Session as QSRules_TLB_2_0_0_151.SessionClass).Cashier.Number );
    end else

  if Supports(Session, QSRules_TLB_2_0_0_105.SessionClass) then
    Begin
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Name', (Session as QSRules_TLB_2_0_0_105.SessionClass).Cashier.Name );
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Number', (Session as QSRules_TLB_2_0_0_151.SessionClass).Cashier.Number );
    end

end;

There is 4 or 5 different versions of dll all with different GUID's bu 98% of code is the same between all of them. Doing that in this way is unnessesary multiplying the code.

Is there any way that I can shorten it ?

I also tried

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
var
 _Session: SessionClass;
begin

  if Supports(Session, QSRules_TLB_2_0_0_151.SessionClass) then
    _Session = (Session as QSRules_TLB_2_0_0_151.SessionClass)

  else if Supports(Session, QSRules_TLB_2_0_0_105.SessionClass) then
      _Session = (Session as QSRules_TLB_2_0_0_105.SessionClass);

  with _Session do
  Begin
      CodeSite.Send( csmLevel1, '_Session.Cashier.Name', Cashier.Name );
      CodeSite.Send( csmLevel1, '_Session..Cashier.Number', Cashier.Number );
  End;

end;

But this not work because variable type can be assigned only from only unit.

Any help appreciated !

You say that the interfaces have different guids in different versions. That is perfectly fine as long as the newer interfaces derive from the older interfaces. Is that actually the case? If they do, then you can simplify your code by casting your Session object to whatever interface actually defines the Cashier member. You do not need to cast it to each individual interface type unless the interfaces do not derive from each other. Can you show the actual interface declarations?

Cashier declaration from v2.0.0.105

_Cashier = interface(IDispatch)
    ['{AA84B4FB-AA41-4423-A763-59D0723ED52B}']
    function Get_Session: _SessionClass; safecall;
    function Get_CashDrawer: _CashDrawer; safecall;
    function Get_OverShortLimitType: overshortlimitEnum; safecall;
    function Get_MaxOverShortAmount: Currency; safecall;
    function Get_MaxOverShortPercent: Double; safecall;
    function Get_SecurityLevel: Smallint; safecall;
    function Get_HasPrivilege(var CashierPrivilege: cashierprivilegesEnum): WordBool; safecall;
    function Get_FailedLogOnAttempts: Integer; safecall;
    function Get_EmailAddress: WideString; safecall;
    function Get_Messages: _CashierMessages; safecall;
    function Get_UnreadMessageCount: Integer; safecall;
    function Get_Name: WideString; safecall;
    function Get_FirstName: WideString; safecall;
    function Get_LastName: WideString; safecall;
    function Get_ReturnLimit: Currency; safecall;
    function Get_FloorLimit: Currency; safecall;
    function Get_ID: Integer; safecall;
    function Get_CashDrawerNumber: Smallint; safecall;
    function Get_Loaded: WordBool; safecall;
    function Get_Number: WideString; safecall;
    property Session: _SessionClass read Get_Session;
    property CashDrawer: _CashDrawer read Get_CashDrawer;
    property OverShortLimitType: overshortlimitEnum read Get_OverShortLimitType;
    property MaxOverShortAmount: Currency read Get_MaxOverShortAmount;
    property MaxOverShortPercent: Double read Get_MaxOverShortPercent;
    property SecurityLevel: Smallint read Get_SecurityLevel;
    property HasPrivilege[var CashierPrivilege: cashierprivilegesEnum]: WordBool read Get_HasPrivilege;
    property FailedLogOnAttempts: Integer read Get_FailedLogOnAttempts;
    property EmailAddress: WideString read Get_EmailAddress;
    property Messages: _CashierMessages read Get_Messages;
    property UnreadMessageCount: Integer read Get_UnreadMessageCount;
    property Name: WideString read Get_Name;
    property FirstName: WideString read Get_FirstName;
    property LastName: WideString read Get_LastName;
    property ReturnLimit: Currency read Get_ReturnLimit;
    property FloorLimit: Currency read Get_FloorLimit;
    property ID: Integer read Get_ID;
    property CashDrawerNumber: Smallint read Get_CashDrawerNumber;
    property Loaded: WordBool read Get_Loaded;
    property Number: WideString read Get_Number;
  end;

Cashier declaration from v2.0.0.151

_Cashier = interface(IDispatch)
    ['{39B2C128-00F1-4834-B1A4-05197C708BD9}']
    function Get_Session: _SessionClass; safecall;
    function Get_CashDrawer: _CashDrawer; safecall;
    function Get_OverShortLimitType: overshortlimitEnum; safecall;
    function Get_MaxOverShortAmount: Currency; safecall;
    function Get_MaxOverShortPercent: Double; safecall;
    function Get_SecurityLevel: Smallint; safecall;
    function Get_HasPrivilege(var CashierPrivilege: cashierprivilegesEnum): WordBool; safecall;
    function Get_FailedLogOnAttempts: Integer; safecall;
    function Get_EmailAddress: WideString; safecall;
    function Get_Messages: _CashierMessages; safecall;
    function Get_UnreadMessageCount: Integer; safecall;
    function Get_Name: WideString; safecall;
    function Get_FirstName: WideString; safecall;
    function Get_LastName: WideString; safecall;
    function Get_ReturnLimit: Currency; safecall;
    function Get_FloorLimit: Currency; safecall;
    function Get_ID: Integer; safecall;
    function Get_CashDrawerNumber: Smallint; safecall;
    function Get_Loaded: WordBool; safecall;
    function Get_Number: WideString; safecall;
    function Get_PasswordAge: Integer; safecall;
    function Get_ReminderPeriod: Integer; safecall;
    function Get_PasswordResetFlag: WordBool; safecall;
    function Get_IsPasswordChanged: WordBool; safecall;
    procedure Set_IsPasswordChanged(var Param1: WordBool); safecall;
    function Get_TimecardID: Integer; safecall;
    procedure Set_TimecardID(var Param1: Integer); safecall;
    function ValidatePassword(var Password: WideString): WordBool; safecall;
    function IsPwdDuplicated(var CashierNumber: Integer; var Password: WideString): WordBool; safecall;
    property Session: _SessionClass read Get_Session;
    property CashDrawer: _CashDrawer read Get_CashDrawer;
    property OverShortLimitType: overshortlimitEnum read Get_OverShortLimitType;
    property MaxOverShortAmount: Currency read Get_MaxOverShortAmount;
    property MaxOverShortPercent: Double read Get_MaxOverShortPercent;
    property SecurityLevel: Smallint read Get_SecurityLevel;
    property HasPrivilege[var CashierPrivilege: cashierprivilegesEnum]: WordBool read Get_HasPrivilege;
    property FailedLogOnAttempts: Integer read Get_FailedLogOnAttempts;
    property EmailAddress: WideString read Get_EmailAddress;
    property Messages: _CashierMessages read Get_Messages;
    property UnreadMessageCount: Integer read Get_UnreadMessageCount;
    property Name: WideString read Get_Name;
    property FirstName: WideString read Get_FirstName;
    property LastName: WideString read Get_LastName;
    property ReturnLimit: Currency read Get_ReturnLimit;
    property FloorLimit: Currency read Get_FloorLimit;
    property ID: Integer read Get_ID;
    property CashDrawerNumber: Smallint read Get_CashDrawerNumber;
    property Loaded: WordBool read Get_Loaded;
    property Number: WideString read Get_Number;
    property PasswordAge: Integer read Get_PasswordAge;
    property ReminderPeriod: Integer read Get_ReminderPeriod;
    property PasswordResetFlag: WordBool read Get_PasswordResetFlag;
    property IsPasswordChanged: WordBool read Get_IsPasswordChanged write Set_IsPasswordChanged;
    property TimecardID: Integer read Get_TimecardID write Set_TimecardID;
  end;

As you can see there is few things added in the later version but there is no doubt that I need to check the software version when calling them functions. Cashier that's only one of 25-30 types there so if I have to write the same basic implementation for all versions .... big task, and horrible code for modifications in later stage.

Finally got it sorted ! Just share the answer in case anyone else looking for it.

The key for success is "late binding", that means you don't use interface.

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
var
 _Session: Variant;
begin

  _Session := Session;

  CodeSite.Send( csmLevel1, '_Session.Cashier.Name', _Session.Cashier.Name );
  CodeSite.Send( csmLevel1, '_Session.Cashier.Number', _Session.Cashier.Number );

end;

With variant variable the functions are not check by compiler but in runtime, so you have to make sure that the spelling is correct because intellisense is not checking it.

Works like a dream !

Thanks all of you anyway !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM