TLDR: Is there a way to run cleanup code when an extension is uninstalled?
I am the author of the WordCount Bookmarked Sections extension. It sets up a function to run OnSave event, using the code below. But it turns out that when someone uninstalls my extensions, that OnSave event is still set and when you save it causes an error. How can I make the extension manager run my cleanup code to remove the OnSave event during uninstallation?
I know how to write the cleanup function. I just can't get LibreOffice to call it during uninstallation.
Sub setup_on_save()
' Call this subroutine to connect the LibreOffice "Save Document" event to the Basic macro `on_save()`.
' It needs to be added to globalEventBroadcaster instead of to ThisComponent because
' otherwise libreoffice produces a warnings that this document has macros.
Dim aProps(1) As New com.sun.star.beans.PropertyValue
aProps(0).Name = "EventType"
aProps(0).Value = "Script"
aProps(1).Name = "Script"
aProps(1).Value = "vnd.sun.star.script:Wordcounter.wordcount_sections.on_save?language=Basic&location=application"
oGlobalEventBroadcaster = GetDefaultContext().getByName( "/singletons/com.sun.star.frame.theGlobalEventBroadcaster" )
oGlobalEventBroadcaster.Events.replaceByName("OnSave", aProps())
End Sub
Last edited by Hagar Delest on Tue Jun 13, 2023 8:33 am, edited 1 time in total.
Reason:tagged solved.
Could your extension add the onSave event sub in the the User Standard library after installation - eg on first running of the extension - then within that sub it tests for and reassigns the event if the extension has been uninstalled?
Edit:
Or/and provide an uninstall script the user has to use instead of the inbuilt extensions dialog.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
Woah. Dodgy as. But thanks.
Is 88B2 just a random number you made up or is it some kind of special magic number?
Do you know whether this is a standard technique for an uninstall hook?
Its a random name as you might already have a "Module1" or something else like that.
No, not a standard technique. I'm just brainstorming for a solution. Assuming the uninstallation routine doesn't do that bit of the cleanup properly, you need a workaround.
Another approach would be to leave the user to assign the event to the macro - then they'll know how to remove it after uninstallation.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
Sub setupOnSave()
' Connects the LibreOffice "Save Document" event to our Basic subroutine `GlobalOnSave()`.
' It adds OnSave to globalEventBroadcaster instead of ThisComponent (current doc) because
' otherwise LibreOffice produces a warning that this document has macros.
' Copies a stub subroutine GlobalOnSave() into the Standard library
' so that OnSave doesn't produce errors even if the extension is uninstalled.
copy_code("Wordcounter", "wordcount_sections", "Standard", "wordcount_sections", "copy_marker")
Dim aProps(1) As New com.sun.star.beans.PropertyValue
aProps(0).Name = "EventType"
aProps(0).Value = "Script"
aProps(1).Name = "Script"
aProps(1).Value = "vnd.sun.star.script:Standard.wordcount_sections.GlobalOnSave?language=Basic&location=application"
oGlobalEventBroadcaster = GetDefaultContext().getByName( "/singletons/com.sun.star.frame.theGlobalEventBroadcaster" )
oGlobalEventBroadcaster.Events.replaceByName("OnSave", aProps())
End Sub
Sub copy_code(fromlib, frommod, tolib, tomod, marker)
' Copy code after _marker_ from fromlib/frommod into module tolib/tomod
libs = globalscope.basiclibraries
libs.loadlibrary(fromlib)
libr = libs.getbyname(fromlib)
module = libr.getbyname(frommod)
textSearch = CreateUnoService("com.sun.star.util.TextSearch")
options = CreateUnoStruct("com.sun.star.util.SearchOptions")
options.algorithmType = com.sun.star.util.SearchAlgorithms.REGEXP
options.searchString = "_" & marker & "_"
textSearch.setOptions(options)
found = textSearch.searchForward(module, 0, Len(module))
code = right(module, Len(module) - found.endOffset(0) - 1)
libr = libs.getbyname(tolib)
if not libs.hasbyname(tolib) then
libs.insertbyname(tolib)
end if
if not libr.hasbyname(tomod) then
libr.insertbyname(tomod,code)
else
libs.loadlibrary(tolib)
'libr.removebyname(tomod)
libr.replacebyname(tomod,code)
end if
libs.storelibraries()
End Sub
' The rest of this file gets copied to Standard library so OnSave doesn't create an error if extension is uninstalled
' _copy_marker_
Sub GlobalOnSave(oEvent As Object)
' This subroutine gets connected to the "Save Document" event of LibreOffice, OnSaveAs.
' It provides a stub so that the OnSave event doesn't create errors even if the Wordcounter extension is removed
library = "Wordcounter"
if globalscope.basiclibraries.hasbyname(library) then
basiclibraries.loadLibrary(library)
Wordcounter.wordcount_sections.OnSave(oEvent)
end if
End Sub