Jump to content
ertank

Type Library (COM) Problem

Recommended Posts

Hello,

 

I am using Delphi 10.4.2.

 

There is a type library that can be accessed using COM. I can import it and use some parts like login, disconnect, version. There are other parts to do database operations and it seems Delphi has problems using those parts of it.

 

1- No interface retrieved

var
  LQuery: IQuery;
 begin
  LQuery := FMainConnection.NewQuery(); 
  // Here LQuery still remains as nil
 end;

2- Access Violation

var
  LInvoice: IData;
  LInvoiceLines: ILines
  ATime: OleVariant;
begin
  LInvoice := FMainConnection.NewDataObject(doSalesInvoice);
  try
    LInvoice.New();
    LInvoice.DataFields.FieldByName('TYPE').Value := 8;
    LInvoice.DataFields.FieldByName('NUMBER').Value := 'L0129002';
    LInvoice.DataFields.FieldByName('DOC_NUMBER').Value := 'L0129002';
    LInvoice.DataFields.FieldByName('AUXIL_CODE').Value := 'AUTO';
    LInvoice.DataFields.FieldByName('DATE').Value := '29.01.2022';
    FMainConnection.PackTime(12, 12, 12, ATime);
    LInvoice.DataFields.FieldByName('TIME').Value := ATime;
    LInvoice.DataFields.FieldByName('ARP-CODE').Value := '320.01.002'; // Here Access Violation raises
    LInvoiceLines := LInvoice.DataFields.FieldByName('TRANSACTIONS').Lines;

 

However, If I try all of these using Visual Studio C#.NET, everything works. Since this is COM object, codes on both Visual Studio and Delphi are almost identical.

Both Delphi and Visual Studio installed on my development computer. They are using same Type Library, same dll files and it is only Delphi fails to use its parts.

 

I wonder if there is some catch to do with Delphi to fix such problems as I am not experienced much using type libraries. Any help is appreciated.

 

Thanks & Regards,

Ertan

Share this post


Link to post
LInvoice.DataFields.FieldByName('AUXIL_CODE').Value := 'AUTO';

here you use underscore

LInvoice.DataFields.FieldByName('ARP-CODE').Value := '320.01.002'; // Here Access Violation raises

here you use a hyphen. Is it simply that the field doesnt exist. That would cause an access violation

 

 

I would first focus on why LInvoice.DataFields.FieldByName('ARP-CODE') seems to be NIL

 

 

On the 

 

var
  LQuery: IQuery;
 begin
  LQuery := FMainConnection.NewQuery(); 
  // Here LQuery still remains as nil
 end;

is IQuery the interface from the COM library? how is the COM interface look in the TLB.pas file? is it a function with no parameters?

 

I would review all the basics and see there is nothing simple being missed. Is there anything else missing from setting up the FMainConnection that might have it returning a NIL interface? 

Share this post


Link to post
2 hours ago, Martin Sedgewick said:

I would first focus on why LInvoice.DataFields.FieldByName('ARP-CODE') seems to be NIL

It is a shame that I did not see that at all. Changing into ARP_CODE and there is no access violation on that line. Thanks.

However, when I try to post an invoice, now I get "Catastrophic failure" error. Below is the final state of my test code. It works down to LInvoice.Post()

I compared code with C# working code. Price, Code, quantity etc assigned are identical. They are test values anyway.

  LInvoice := FComConnection.NewDataObject(doSalesInvoice);
  try
    LInvoice.New();
    LInvoice.DataFields.FieldByName('TYPE').Value := 8;
    LInvoice.DataFields.FieldByName('NUMBER').Value := '~';
    LInvoice.DataFields.FieldByName('DATE').Value := '29.01.2022';
    FComConnection.PackTime(12, 12, 12, LTime);
    LInvoice.DataFields.FieldByName('TIME').Value := LTime;
    LInvoice.DataFields.FieldByName('ARP_CODE').Value := '320.01.002';
    LInvoiceLines := LInvoice.DataFields.FieldByName('TRANSACTIONS').Lines;
    LInvoiceLines.AppendLine();
    LInvoiceLines[I].FieldByName('TYPE').Value := 0;
    LInvoiceLines[I].FieldByName('MASTER_CODE').Value := 'M.01.003';
    LInvoiceLines[I].FieldByName('QUANTITY').Value := 5.5 + I;
    LInvoiceLines[I].FieldByName('PRICE').Value := 3.5 + I;
    LInvoiceLines[I].FieldByName('VAT_RATE').Value := 8;
    LInvoiceLines[I].FieldByName('UNIT_CODE').Value := 'KG';
    if not LInvoice.Post() then  // <--- Here Catastrophic failure
    begin
      if LInvoice.ErrorCode <> 0 then
      begin
        FLog.LogError('Cannot post invoice: ' + IntToStr(LInvoice.ErrorCode) + ', ' + LInvoice.ErrorDesc);
        Exit();
      end;
    end;
    FLog.LogInfo('Internal reference: ' + LInvoice.DataFields.FieldByName('INTERNAL_REFERENCE').Value);

Code is actually in try..except block, "Catastrophic error" is catched in except and logged. But I did not include it here

2 hours ago, Martin Sedgewick said:

is IQuery the interface from the COM library? how is the COM interface look in the TLB.pas file? is it a function with no parameters?

IQuery is an interface from the COM library, yes. Below part is what I see in TLB file for IQuery. I can share whole TLB it in private message if you would like to look at different parts of it. It is almost 10k lines.

// Initial definition
IQuery = interface;
  
// another line
Query = IQuery;

// function definition inside COM main interface
function NewQuery: IQuery; safecall;


// *********************************************************************//
// Interface: IQuery
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {3A1DB335-35DB-463B-AF5C-6BA2B143E65A}
// *********************************************************************//
  IQuery = interface(IDispatch)
    ['{3A1DB335-35DB-463B-AF5C-6BA2B143E65A}']
    function Get_name: WideString; safecall;
    procedure Set_name(const Value: WideString); safecall;
    function Get_Statement: WideString; safecall;
    procedure Set_Statement(const Value: WideString); safecall;
    function Get_Error: Integer; safecall;
    function Get_QueryFields: IQueryFields; safecall;
    function FieldByName(const fieldName: WideString): IQueryField; safecall;
    function Execute: WordBool; safecall;
    function OpenDirect: WordBool; safecall;
    procedure Close; safecall;
    function First: WordBool; safecall;
    function Next: WordBool; safecall;
    function Previous: WordBool; safecall;
    function Last: WordBool; safecall;
    function Get_SQLClause: ISQLClause; safecall;
    function GetDateString(ADate: TDateTime): WideString; safecall;
    function Get_DBErrorDesc: WideString; safecall;
    property name: WideString read Get_name write Set_name;
    property Statement: WideString read Get_Statement write Set_Statement;
    property Error: Integer read Get_Error;
    property QueryFields: IQueryFields read Get_QueryFields;
    property SQLClause: ISQLClause read Get_SQLClause;
    property DBErrorDesc: WideString read Get_DBErrorDesc;
  end;

 

 

2 hours ago, Martin Sedgewick said:

I would review all the basics and see there is nothing simple being missed. Is there anything else missing from setting up the FMainConnection that might have it returning a NIL interface? 

I doubt FMainConnection (now FComConnection) setting is wrong as I can do some other operations using it. Login, Disconnect, GetVersion, LastError, LastErrorString, GetTablename etc. But, it is a fact that I could not see that "hyphen" and "underscore" thing for a couple of days.

 

Thanks & Regards,

Ertan

Share this post


Link to post

looks like something internal when posting. The only thing I could offer is try to post with the minimum possible - empty record? without appending lines etc, which might help diagnose something wrong.

Share this post


Link to post

I have never worked with TLB, but as a guess... 

Does method LInvoice.Edit ( or similar ) exist? What if You try to use LInvoice.Edit () instead of LInvoice.New?

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×