LibreOffice events listener lazarus / 67-Windows ---------------------------------------------------------------------- chris_laz · 2024-10-07 08:13 Hi all, I am attempting to port a Delphi app which runs LibreOffice by automation and listens for document save and close events, but I can't quite get it to work in Lazarus. I am using Lazarus 3.6/FPC 3.22 on Windows 10, with LibreOffice 7.4 (all 64bit). The Delphi code implements an event listener for LO by implementing a TAutoObject with an IConnectionPointContainer, but I can't get this to work in Lazarus, as FPC does not appear to include any implementations of the IConnectionPointContainer interface (Delphi has a TConnectionPoints class). I have tried reimplementing this, but with no success so far. I can run LO and open a doc in Calc successfully, but my event listener does nothing (but doesn't crash). Has anyone managed to implement an event listener for LO in Lazarus? I can share the code I've tried so far if that's any help, or if there is a pre-built event listener somewhere, that would also be a great help! Thanks ---------------------------------------------------------------------- cdbc · 2024-10-07 08:20 Hi Yup, let's see the code you have so far...  Crystal balls are hard to program with  Regards Benny ---------------------------------------------------------------------- egsuh · 2024-10-07 08:33 Yes, I'd like to see your codes as well... (to learn more... ^^) ---------------------------------------------------------------------- chris_laz · 2024-10-07 09:10 OK here goes - In main unit Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var       libreMgr, libreDsk, libreDoc: OleVariant;      libreEvents: ILibreOfficeEvents; ...       libreMgr := CreateOleObject('com.sun.star.ServiceManager');      libreDsk := LibreMgr.createInstance('com.sun.star.frame.Desktop');       libreDoc := libreDsk.loadComponentFromFile(filename etc...);       libreEvents := TLibreOfficeEvents.Create;      libreEvents.OnPrepareUnload := event handler method       libreDoc.addEventListener(libreEvents);  See attached units LibreOfficeEventListener - implementation of TLibreOfficeEvents with internal ILibreOfficeEvents declaration LibreOfficeEventListener_TLB - imported LO type library, declaration of LO ILibreOfficeEventListener interface ActiveXConnectionPoints - custom implementation of IConnectionPointContainer ComServNoRegisterLaz - override default FPC TComServer implementation to remove registry updates I am not sure where my original Delphi implementation came from (back in 2011), I must have found some hints online, as I am pretty sure I did not work this all out for myself. The LO type library must be loaded as a resource in the exe, but does not need to be added to the registry. This allows the app to run without admin privileges, hence the overrides of the default TComServer and TAutoObjectFactory to remove registry updates. This all compiles OK in Lazarus, but the events do not fire at all after the LO document is opened and the event listener is added, and there are no runtime errors. ---------------------------------------------------------------------- chris_laz · 2024-11-12 14:31 No suggestions? Has anyone else managed to hook LibreOffice automation events in a Lazarus app? ---------------------------------------------------------------------- marcov · 2024-11-12 15:16 Could you also add a small project to see how you test? I can at least test it on development versions of FPC. ---------------------------------------------------------------------- chris_laz · 2024-11-12 16:18 OK, here's a very simple test project, supplied as a zip. It should compile as-is in Lazarus, all required units are included (I think), plus a sample CSV file. A form with one button and a memo. Click the button to open a CSV file in Calc. Start editing the CSV, and Calc's OnModified events should be logged in the memo - but nothing happens here, so obviously my plumbing is wrong. I have Lazarus 3.6, FPC 3.2.2 ---------------------------------------------------------------------- Curt Carpenter · 2024-11-12 17:18 Quote from: chris_laz on October 07, 2024, 11:10:26 amI am not sure where my original Delphi implementation came from (back in 2011), I must have found some hints online, as I am pretty sure I did not work this all out for myself. I've been wrestling with some old code issues for the past two weeks too -- wonderfully frustrating isn't it?  So many things have changed in the past thirteen years (across so many different interfaces in your case -- mine is much simpler   ). ---------------------------------------------------------------------- chris_laz · 2024-12-31 14:25 Just a thread bump, does anyone have any experience automating LibreOffice with Lazarus to share? Thanks ---------------------------------------------------------------------- rvk · 2025-01-02 10:28 I'm not familiar with OO and LO automation via TLB... but when diving into this... I see you used XEventListener. If I look at the documentation of XEventListener I see it is deprecated: https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1 _1document_1_1XEventListener.html XDocumentEventListener would be the new one: https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1 _1document_1_1XDocumentEventListener.html It also states it uses XDocumentEventBroadcaster to be notified: https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1 _1document_1_1XDocumentEventBroadcaster.html And XDocumentEventBroadcaster has a addDocumentEventListener, removeDocumentEventListener and notifyDocumentEvent. Shouldn't those be used??? And more... you are now using the COM style code to create a LibreOffice document, but are using the TLB style code to interact with it. I'm not sure if you can mix those. ---------------------------------------------------------------------- marcov · 2025-01-02 13:11 I traced through it yesterday on 32-bit to see where it goes wrong. I don't see calls failing, but the notifyevent callback doesn't get call, nor some of the "advise" methods. Does this work in Delphi with current versions of LO ?   64-bit ? ---------------------------------------------------------------------- chris_laz · 2025-01-02 14:07 Hi marcov, Yes, that's what I found when tracing through it. Nothing crashes, but the event sink never seems to be triggered. This code works in Delphi 2006 (32bit) with LibreOffice 7.4. I've not tried it with the most recent versions of LO. I've not tried compiling it in Lazarus as a 32bit exe. ---------------------------------------------------------------------- marcov · 2025-01-02 16:02 I tried FPC 3.3.x with a LO 7.6 in both 32-bit and 64-bit. I do have delphi, but only unicode versions (Seattle aka XE10) ---------------------------------------------------------------------- marcov · 2025-01-02 18:17 I tested with delphi, and after changing the units somewhat for different interfaces, it works with XE 10 32-bit with the same LO. So the setup is not the problem, the FPC compiled binary is. I also tried some header changes to no avail. (the 2nd type of the next parameter mostly) ---------------------------------------------------------------------- korba812 · 2025-01-04 15:58 It seems that the problem is a small bug in the TAutoObject.GetTypeInfo function - should return DispTypeInfo instead of ClassInfo. ---------------------------------------------------------------------- marcov · 2025-01-04 17:34 Quote from: korba812 on January 04, 2025, 04:58:47 pmIt seems that the problem is a small bug in the TAutoObject.GetTypeInfo function - should return DispTypeInfo instead of ClassInfo. ... and it works trunk commit ac510d391f9d784a00275836715a25a41331460f thanks! Still exceptions when closing (RPC server something) it seems. ---------------------------------------------------------------------- Thaddy · 2025-01-04 20:55 That is probably the same as with ms: you need to mask out all floating point exceptions, e.g, from memory Set8087CW  with $1332 controlword. This is only needed on Windows32, not on nixes or 64bit. If necessary on other platforms, use SetExceptionMask instead and don't forget to restore on exit. ---------------------------------------------------------------------- korba812 · 2025-01-04 23:45 I can also see this message if I close LibreOffice before closing sample project. But this looks like a logic error of example project - in the FormClose event there is an attempt to operate on a LibreOffice instance that no longer exists. ---------------------------------------------------------------------- chris_laz · 2025-01-06 16:45 Brilliant, thanks guys. That has fixed it. I suspected it was something simple like this, I just hadn't got as far as combing through the existing FPC source to double-check these things. For the moment, rather than downloading a dev build of FPC, I've just re-implemented the TAutoObject in my LibreOfficeEventListener unit, with the required fix in the GetTypeInfo method: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TAutoObjectBugFixed.GetTypeInfo(Index, LocaleID: longint; out TypeInfo): HResult; stdcall;begin   if Index<>0 then Result := DISP_E_BADINDEX   else begin      ITypeInfo(TypeInfo) := TAutoObjectFactory(Factory).DispTypeInfo; // bug fix for FPC 3.2.2, was returning ClassInfo      Result := S_OK;   end;end;  Thanks again!