Adrianvdh wrote:Code: Select all
::MY_PROGRAM_PLUGIN
set version=1.0
call :callcuntion :function, mainmenu 5 n
:function
echo It works^^!
pause
exit /b
The problem with this is, that the batch file will be executed from the first line, so the
"call :callfunction ..." line will be executed and after that the function code, as there is no goto.
I think (or better i hope), i've now understood how you wanted to design this system.
The problem seems to be (IF i have really understood it), that you call ":callfunction" for both:
- registering the functions to the main system, and
- executing the function within the main system.
That was (beside others) a little bit irritating.
But although this is possible, i would prefer to just split functionality, so the plugin doesn't call
the main batch's internal functions; instead it is allowed to access a "batch-dll".
Adrianvdh wrote:Can't it be, what if my batch file has a 'getWinKey' function that contains Windows serial key, but the plugin wants to copy the serial key from a variable and echo it.
If the main.bat is not a batch file with self-modifying code, then there should be no (big) problem:
The main.bat then needs to offer a switch that directly calls the needed function, if allowed (security check may be implemented).
But in terms of programming this is not an example of good programming style or practices:
Technically there is a subgroup of *.exe that may export functions, as *.dll: Portable Executables.
But although this is possible, there are many reasons, why they should be avoided
(and it IS avoided in most systems: i've found no example where it was mixed up, although i'm far away from knowing all programs in the world):
- security issues
- easily produce dead locks,
- easily produce complex endless loops
- ...
Although i'm not sure if all, or if not all, which of these problems could be realized using batch, even if you want.
But if i understand it right, you also want to do this in ANSI C, too.
So you better divide the functionality:
- one or multiple "dll-batch" files to be called from other batches (main and plugins) to execute the "dll-batch"'s functions
- a main batch file that manages plugins, and may call functions from dll-batches
- plugin.bat that is called from main, and may call functions from dll-batches
This is an example of how it could be implemented:
Lets assume the following describe their function by name the following is given:
Sample.dll.bat [/list|/call functionName parameter(s)]
/list returns a list of all exported functions
/call executes a function, if it is an exported function,
an appropriate error message is displayed else.
functionName denotes a label that defines an exported function
parameter(s) one or more parameters.
If no parameter is used, then an appropriate error message is displayed.
SampleMain.bat
Plugins are allowed, under the terms of this plugin contract:
Batch files, that should be used as plugins:
- have to be be placed within the SampleMain.bat's subfolder named "plugins",
- must have "@rem " as the first 4 bytes followed by "MY_BATCH_FILE_NAME_TEXT " followed by the name of the function that should be replaced followed by <\r\n>.
plugins/SamplePlugin.bat:
As a plugin for SampleMain.bat, it meets the requirements of the plugin contract.
I've tried to use as many of your specifications, to implement an example of such a system.
But i've changed the definition of the :callfunction.
The advantage is, that it is much easier now, to define "batch-plugins".
So this is such an example system;
Sample.dll.bat
Code: Select all
:: processing parameters
@ if /I .%1 == ./list if .%2 == . goto :list
@ if /I .%1 == ./call goto :call
@ goto :help
:call
@ for /F %%e in ('call %~f0 /list') do @(
if /I "%%~e" == "%2" goto %%~e
)
@ echo No such exported function found: %0 %*.
@ exit /b 1
:SampleFunction
@ echo Successfully called: %0 %*
@ exit /b 0
:list
@ for %%e in (
":SampleFunction"
) do @(
echo(%%~e
)
@ exit /b 0
:help
@ for %%h in (
"Sample.dll.bat [/list|/call functionName parameter(s)]"
" /list returns a list of all exported functions"
" /call executes a function, if it is an exported function,"
" an appropriate error message is displayed else."
" functionName denotes a label that defines an exported function"
" parameter(s) one or more parameters."
""
) do @(
echo(%%h
)
@ exit /b 0
SampleMain.bat
Code: Select all
@echo off
setlocal enableDelayedExpansion
cls
:: initiate
set "PluginFunctions.length=3"
set "PluginFunctions[Pluginable1]=2"
set "PluginFunctions[Pluginable2]=3"
set "PluginFunctions[Pluginable3]=1"
set "PluginFunctions[1]=call :Pluginable3"
set "PluginFunctions[2]=call :Pluginable1"
set "PluginFunctions[3]=call :Pluginable2"
set "usePlugins=true"
goto :processParams
:processParams
if /I .%1 == ./noPlugins set "usePlugins=false"
goto :pluginManager
:pluginManager
if %usePlugins% == false goto :main
for %%f in (plugins\*.bat) do (
set "header="
(set /P "header=" < %%f)
for /F "tokens=1-3" %%r in ("!header!") do (
if .%%r%%s == .@remMY_BATCH_FILE_NAME_TEXT (
set "PluginFunction=%%~t"
set "PluggedInFunction=%%~f"
for /F %%p in ("!PluginFunction::=!") do (
set "PluginFunctions[!PluginFunctions[%%~p]!]=call "!PluggedInFunction!""
)
)
)
)
goto :main
:main
echo call Sample.dll.bat from main
call Sample.dll.bat /call :SampleFunction
goto :mainlabel
:mainlabel
echo =================================================================
::2
::3
::4
call :callfunction :Pluginable1, mainlabel 5 n
echo =================================================================
:default
::1
call :callfunction :Pluginable2, default 2 n
echo =================================================================
:settings
::1
::2
call :callfunction :Pluginable3, settings 2 n
::4
::5
echo =================================================================
exit /b 0
:callfunction
set "params=%*"
set "command=%1"
for /F %%c in ("!PluginFunctions[%command::=%]!") do set "command=!PluginFunctions[%%~c]!"
%command% %params:* =%
exit /b %ErrorLevel%
:Pluginable1
echo %0 :Pluginable1
echo params: %*
exit /b 0
:Pluginable2
echo %0 :Pluginable2
echo params: %*
exit /b 0
:Pluginable3
echo %0 :Pluginable3
echo params: %*
exit /b 0
plugins\SamplePlugin.bat
Code: Select all
@rem MY_BATCH_FILE_NAME_TEXT :Pluginable2
@echo(This is the test function that is shown in the main batch file :)
@echo(
@echo(call Sample.dll.bat /call :SampleFunction
@call Sample.dll.bat /call :SampleFunction
@echo(Notice: The working directory is that of the SampleMain.bat file.
@echo(
@echo(Finished
@exit /b
plugins\NoPlugin.bat
Code: Select all
@echo MY_BATCH_FILE_NAME_TEXT MY_BATCH_FILE_NAME_TEXT2 MY_BATCH_FILE_NAME_TEXT3
plugins\NoPlugin2.bat
I know it is not exact, what you wanted to do, but i think this is:
- easier to read
- easier to implement
penpen