Page 1 of 1
[Solved] Extension uninstall cleanup hook
Posted: Thu May 11, 2023 5:56 am
by Berwyn
Hello,
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.
My setup code is:
Code: Select all
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
Re: Extension uninstall cleanup hook
Posted: Thu May 11, 2023 9:32 am
by JeJe
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.
Re: Extension uninstall cleanup hook
Posted: Thu May 11, 2023 9:46 am
by Berwyn
Really? Can a macro add itself to another library? How?
Re: Extension uninstall cleanup hook
Posted: Thu May 11, 2023 10:20 am
by JeJe
Code: Select all
dim libs,libraryname,modulename,subst,modl
libraryname = "Standard"
modulename = "Module88B2"
subst = "Sub NewSub" & chr(13) & "End Sub"
libs = globalscope.basiclibraries
if libs.hasbyname(libraryname)=false then
libs.insertbyname(libraryname)
end if
libr = libs.getbyname(libraryname)
if libr.hasbyname(modulename) = false then
modl=libr.insertbyname(modulename,subst)
else
'modl = libr.getbyname(modulename)
libs.loadlibrary(libraryname)
newst= libr.getbyname(modulename)
newst = newst & chr(13) & chr(13) & subst
libr.replacebyname(modulename,newst)
end if
libs.storelibraries
Re: Extension uninstall cleanup hook
Posted: Thu May 11, 2023 12:10 pm
by Berwyn
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?
Re: Extension uninstall cleanup hook
Posted: Thu May 11, 2023 1:43 pm
by JeJe
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.
Re: Extension uninstall cleanup hook
Posted: Tue Jun 13, 2023 4:23 am
by Berwyn
I actually got this working using the following code:
Code: Select all
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