一种在 libreoffice basic 中通过运行时代码添加子例程的方法

A way to add subroutines by code at runtime in libreoffice basic

提问人:mutercim 提问时间:9/14/2023 更新时间:9/14/2023 访问量:35

问:

有没有办法在 libreoffice basic 中通过运行时通过代码添加/删除子例程或函数?

我非常希望能够在运行时通过代码创建、删除和运行子例程或函数。我正在考虑这是绕过 libreoffice-basic 中缺少接口(无法进行依赖关系反转)的一种方式。

LibreOffice 基础版 libreoffice-basic openoffice-basic

评论

0赞 JohnSUN 9/14/2023
您正在询问潜在不安全机制的实施 - 即使公开讨论解决此类问题的方法也很危险,因为攻击者可以利用讨论的结果。因此,一个反问:您究竟想使用这种技术实现什么?
0赞 mutercim 9/14/2023
我知道。我试图简要解释一下:我试图绕过 libreoffice basic 无法进行依赖反转(将函数作为变量传递)。我计划动态创建一个函数,其名称为字符串格式,然后运行并销毁它以弥补我无法将函数作为变量传递的问题。
0赞 JohnSUN 9/14/2023
弥补我无法将函数作为变量传递 - 我不确定我是否理解你的困境。这是你要问的吗?
0赞 mutercim 9/14/2023
我想就是这样。无论多么复杂,我猜它都能完成这项工作。谢谢!

答:

0赞 mutercim 9/14/2023 #1

感谢 JohnSUN。因此,似乎您可以使用字符串名称运行宏(尽管很难)。只需检查以下代码即可。

这是示例代码(太长,由您自行清理)

REM CALL A USER-DEFINED FUNCTION FROM AN ARBITRARY LIBRARY
REM Parameters: 
REM funcName - string - name of the user-defined function
REM inpParams - an array of parameters passed to the function (can be empty)
REM libName - string - library Name (default "Standard")
REM In case of an error (no library, no function found, error in the function itself)
REM returns Nothing. Otherwise, the result of execution
REM custom function with the specified parameters.
REM Author: Vladyslav Orlov aka JohnSUN, Ukraine, Kyiv, 2011
REM mailto: [email protected]
Function runMacro(funcName As String, Optional inpParams As Variant, Optional libName)
    Dim oScriptProvider As Object   
    Dim oLib As Object              
    Dim oScript As Object           
    Dim oModuleNames As Object      
    Dim i%                          
    Dim aOutParamIndex(), aOutParam()   ' Dummy arrays, read https://wiki.openoffice.org/wiki/Documentation/DevGuide/Scripting/Scripting_Framework_URI_Specification
    Dim macroName As String         
    Const prefix="vnd.sun.star.script:"
    Const sufix="?language=Basic&location=document"
    runMacro = Nothing
    If IsMissing(inpParams) Then inpParams = Array()
    If Not IsArray(inpParams) Then inpParams = Array(inpParams)
    If IsMissing(libName) Then libName = "Standard"
    BasicLibraries.LoadLibrary(libName)
    If NOT BasicLibraries.isLibraryLoaded(LibName) Then Exit Function
    oLib = BasicLibraries.getByName(libName)
    oScriptProvider = ThisComponent.ScriptProvider
    
    oModuleNames = oLib.getElementNames()
    On Local Error GOTO NextIteration
    For i = LBound(oModuleNames) To UBound(oModuleNames)
        macroName = prefix & libName & "." & oModuleNames(i) & "." & funcName & sufix
        oScript = oScriptProvider.getScript(macroName)
        runMacro = oScript.invoke(inpParams, aOutParamIndex, aOutParam)
        Exit Function
NextIteration:
    Next i
End Function

下面是调用的函数:

REM Macros available for running:

Sub Main
    display("dum", "Fn0")
    display("dum", "Fn1")
End Sub

' FUNCTION USED

Sub display(sFuncName As String, Optional param)
  msgbox (runMacro(sFuncName, param))
End Sub 

Function dum(sFuncName As String) As String 
    dum = "This is DUM(" & sFuncName & "(0)) = " & runMacro(sFuncName, 0) & Chr(10) & _
          "and is DUM(" & sFuncName & "(1)) = " &   runMacro(sFuncName, 1)
End Function 

Function Fn0(iVal As Integer) As String 
    Fn0 = "From Fn0 (" & iVal & ") "
End Function 

Function Fn1(iVal As Integer) As Integer
Static add As Long 
    add = add + 5
    Fn1 = iVal + add
End Function 

评论

0赞 JohnSUN 9/14/2023
不,我建议使用不同的代码。正如您所写的,如果所有函数都在一个模块中,程序将工作,否则将抛出错误。这就是为什么原始解决方案中的调用被移动到具有自己的本地错误处理程序的单独函数的原因。oScriptProvider.getScript(macroName)