在DOS .bat / .cmd脚本中有一个很好的方法来构build函数 。 要模块化一些安装脚本,最好将包含函数库的文件包含到.bat / .cmd脚本中。
我试过的是:
mainscript.bat
call library.bat call:function1
library.bat
goto:eof :stopCalipri -- stop alle prozesse die mit calipri zu tun haben :: -- %~1: argument description here SETLOCAL REM.--function body here set LocalVar1=dummy set LocalVar2=dummy echo "Called function successfully :)" (ENDLOCAL & REM -- RETURN VALUES IF "%~1" NEQ "" SET %~1=%LocalVar1% IF "%~2" NEQ "" SET %~2=%LocalVar2% ) GOTO:EOF
当我打电话给mainscript.bat时,我得到以下输出:Das Sprungziel – function1 wurde nicht gefunden。
什么意思或多或less:找不到名为function1的跳转点
任何想法,或者这是不可能的?
这是可能的,而且有一些不同的方法可以做到这一点。
1)将完整的“库”复制并粘贴到每个文件中Works,但它不是一个真正的库,在所有文件中更改/更正库函数
2)通过调用包装器包含一个库
call batchLib.bat :length result "abcdef"
和batchLib.bat开始
call %* exit /b ... :length ...
编程简单,但速度很慢,因为每个库调用会加载库批处理,并且可能会出现参数问题。
3)“自加载”库BatchLibrary或如何包含批处理文件
它创建每个临时批处理文件,结合自己的代码和库代码。
它在库启动时会执行一些高级功能,如安全参数访问。 但在我看来,它也很容易使用
用户脚本示例
@echo off REM 1. Prepare the BatchLibrary for the start command call BatchLib.bat REM 2. Start of the Batchlib, acquisition of the command line parameters, activates the code with the base-library <:%BL.Start% rem Importing more libraries ... call :bl.import "bl_DateTime.bat" call :bl.import "bl_String.bat" rem Use library functions call :bl.String.Length result abcdefghij echo len=%result%
编辑:另一种方法是…
4)宏库
你可以使用批量宏,很容易包含和使用它们。
call MacroLib.bat set myString=abcdef %$strLen% result,myString echo The length of myString is %result%
但是构建宏很难!
更多关于带参数的批量“宏”的宏观技术
MacroLibrary.bat
set LF=^ ::Above 2 blank lines are required - do not remove set ^"\n=^^^%LF%%LF%^%LF%%LF%^^" :::: StrLen pString pResult set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n% for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n% set "str=A!%%~2!"%\n% set "len=0"%\n% for /l %%A in (12,-1,0) do (%\n% set /a "len|=1<<%%A"%\n% for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n% )%\n% for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n% ) %\n% ) ELSE setlocal enableDelayedExpansion ^& set argv=,
每次执行主文件时,都有一种更简单的方法来加载库函数。 例如:
@echo off rem If current code was restarted, skip library loading part if "%_%" == "_" goto restart rem Copy current code and include any desired library copy /Y %0.bat+lib1.bat+libN.bat %0.full.bat rem Set the restart flag set _=_ rem Restart current code %0.full %* :restart rem Delete the restart flag set _= rem Place here the rest of the batch file rem . . . . . rem Always end with goto :eof, because the library functions will be loaded rem after this code! goto :eof
我想出了一个简单的解决方案,使用外部库的批处理文件,我想问你们测试它,并找到可能的错误。
如何使用:
工作原理:
怎么运行的:
优点:
码:
Your_batch_file.bat
@echo off & setlocal EnableExtensions ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::Your code starts in :_main ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: v1.5 - 01/08/2015 - by Cyberponk - Fixed returning to original path when using RequestAdminElevation :: v1.4 - 25/05/2015 - by Cyberponk :: This module includes funcions from included libraries so that you can call :: them inside the :_main program :: :: Options set "_DeleteOnExit=0" &:: if 1, %_TempFile% will be deleted on exit (set to 0 if using library RequestAdminElevation) ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: (if "%BatchLibraryPath%"=="" set "BatchLibraryPath=.") &set "_ErrorCode=" &set "#include=call :_include" set _LibPaths="%~dp0";"%BatchLibraryPath%"&set "_TempFile=%TEMP%\_%~nx0" echo/@echo off ^& CD /D "%~dp0" ^& goto:_main> "%_TempFile%" || (echo/Unable to create "%_TempFile%" &echo/Make sure the %%TEMP%% path has Read/Write access and that a file with the same name doesn't exist already &endlocal &md; 2>nul &goto:eof ) &type "%~dpf0" >> "%_TempFile%" &echo/>>"%_TempFile%" &echo goto:eof>>"%_TempFile%" &call :_IncludeLibraries (if "%_ErrorCode%"=="" (call "%_TempFile%" %*) else (echo/%_ErrorCode% &pause)) & (if "%_DeleteOnExit%"=="1" (del "%_TempFile%")) & endlocal & (if "%_ErrorCode%" NEQ "" (set "_ErrorCode=" & md; 2>nul)) &goto:eof ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :_include lib set "lib=%~1.bat" &set "_included=" (if EXIST "%lib%" ( set "_included=1" &echo/>> "%_TempFile%" &type "%lib%" >> "%_TempFile%" & goto:eof )) & for %%a in (%_LibPaths%) do (if EXIST "%%~a\%lib%" ( set "_included=1" &echo/>> "%_TempFile%" &type "%%~a\%lib%" >> "%_TempFile%" &goto:endfor)) :endfor (if NOT "%_included%"=="1" ( set "_ErrorCode=%_ErrorCode%Library '%~1.bat' not fount, aborting...&echo/Verify if the environment variable BatchLibraryPath is pointing to the right path - and has no quotes - or add a custom path to line 25&echo/" )) &goto:eof ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :_IncludeLibraries - Your included libraries go here :::::::::::::::::::::::::::::::::::::: :: You can add custom paths to this variable: set _LibPaths=%_LibPaths%; C:\; \\SERVER\folder :: Add a line for each library you want to include (use quotes for paths with space) :: Examples: :: %#include% beep :: %#include% Network\GetIp :: %#include% "Files and Folders\GetDirStats" :: %#include% "c:\Files and Folders\GetDriveSize" :: %#include% "\\SERVER\batch\SendHello" %#include% Example goto:eof ::End _IncludeLibraries ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :_main - Your code goes here :::::::::::::::::::::::::::::::::::::: echo/Example code: call :Example "It works!" echo/____________________ echo/Work folder: %CD% echo/ echo/This file: %0 echo/ echo/Library paths: %_LibPaths% echo/____________________ echo/Argument 1 = %1 echo/Argument 2 = %2 echo/All Arguments = %* echo/____________________ pause
。
Example.bat
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :Example msg ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: setlocal ENABLEEXTENSIONS & set "msg=%1" echo/%msg% endlocal & goto :EOF :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
如果你想要一个简单的方法来设置%BatchLibraryPath%,只需把这个文件放在你的Library路径中,并在运行Your_batch_file.bat之前运行它。 此设置在重新启动时保持不变,因此只运行一次:
SetBatchLibraryPath.bat
setx BatchLibraryPath "%~dp0" pause
另一个解决方案是将库函数临时附加到正在运行的批处理文件。
原始文件可以在更改之前保存在临时文件中,并在完成时恢复。 这有缺点,你需要在最后调用:deimport函数来恢复文件并删除临时文件。 您还需要能够写入批处理文件和当前所在的文件夹。
demo.bat
@ECHO OFF :: internal import call or external import call via wrapper function CALL:IMPORT test.bat "C:\path with spaces\lib 2.bat" :: external import call ::CALL importer.bat "%~f0%" test.bat "C:\path with spaces\lib 2.bat" CALL:TEST CALL:LIB2TEST CALL:DEIMPORT GOTO:EOF :: Internal version of the importer :IMPORT SETLOCAL IF NOT EXIST "%~f0.tmp" COPY /Y "%~f0" "%~f0.tmp">NUL SET "PARAMS=%*" SET "PARAMS=%PARAMS:.bat =.bat+%" SET "PARAMS=%PARAMS:.bat" =.bat"+%" COPY /Y "%~f0"+%PARAMS% "%~f0">NUL ENDLOCAL GOTO:EOF :: wrapper function for external version call :::IMPORT ::CALL import.bat "%~f0" %* ::GOTO:EOF :: Internal version of the deimporter :DEIMPORT IF EXIST "%~f0.tmp" ( COPY /Y "%~f0.tmp" "%~f0">NUL DEL "%~f0.tmp">NUL ) GOTO:EOF
test.bat的
:test ECHO output from test.bat GOTO:EOF
C:\路径与空间\ lib 2.bat
:LIB2TEST ECHO output from lib 2.bat GOTO:EOF
或者使用外部版本。 请注意,这将导入deimport函数,因此请确保在demo.bat文件中将其删除。
import.bat
:: External version of the importer SETLOCAL EnableDelayedExpansion IF NOT EXIST "%~f1.tmp" COPY /Y "%~f1" "%~f1.tmp">NUL SET "PARAMS=%*" SET "PARAMS=!PARAMS:"%~f1" =!" SET "PARAMS=%PARAMS:.bat =.bat+%" SET "PARAMS=%PARAMS:.bat" =.bat"+%" COPY /Y "%~f1"+%PARAMS% "%~f1">NUL :: external version of the importer - remove the internal one before use! ECHO :DEIMPORT>>"%~f1" ECHO IF EXIST ^"%%~f0.tmp^" ^(>>"%~f1" ECHO. COPY /Y ^"%%~f0.tmp^" ^"%%~f0^"^>NUL>>"%~f1" ECHO. DEL ^"%%~f0.tmp^"^>NUL>>"%~f1" ECHO ^)>>"%~f1" ECHO GOTO:EOF>>"%~f1" ENDLOCAL GOTO:EOF
好吧…快速和肮脏,因为我是一个UNIX的家伙…创建您的“库”文件
1 @ECHO OFF<br> 2 SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION & PUSHD<br> 3 :: -----------------------------------------------<br> 4 :: $Id$<br> 5 :: <br> 6 :: NAME:<br> 7 :: PURPOSE:<br> 8 :: NOTES:<br> 9 :: <br> 10 :: INCLUDES --------------------------------- --<br> 11 :: DEFINES --------------------------------- --<br> 12 :: VARIABLES --------------------------------- --<br> 13 :: MACROS --------------------------------- --<br> 14 <br> 15 GOTO :MAINLINE<br> 16 <br> 17 :: FUNCTIONS --------------------------------- --<br> 18 <br> 19 :HEADER<br> 20 ECHO ^<HTML^><br> 21 ECHO ^<HEAD^><br> 22 ECHO ^<TITLE^>%1^</TITLE^><br> 23 ECHO ^</HEAD^><br> 24 ECHO ^<BODY^><br> 25 GOTO :EOF<br> 26 <br> 27 :TRAILER<br> 28 ECHO ^</BODY^><br> 29 ECHO ^</HTML^><br> 30 GOTO :EOF<br> 31 <br> 32 :: MAINLINE --------------------------------- --<br> 33 :MAINLINE<br> 34 <br> 35 IF /I "%1" == "HEADER" CALL :HEADER %2<br> 36 IF /I "%1" == "TRAILER" CALL :TRAILER<br> 37 <br> 38 ENDLOCAL & POPD<br> 39 :: HISTORY ------------------------------------<br> 40 :: $Log$<br> 41 :: END OF FILE --------------------------------- --<br>
这应该是相当直接的你…在第15行,我们跳转到主线开始实际执行。 在第19和27行,我们为我们的例程创建入口点。 第35行和第36行是对内部例程的调用。
现在,你建立的文件,将调用库例程..
1 @ECHO OFF<br> 2 SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION & PUSHD<br> 3 :: -----------------------------------------------<br> 4 :: $Id$<br> 5 :: <br> 6 :: NAME:<br> 7 :: PURPOSE:<br> 8 :: NOTES:<br> 9 :: <br> 10 :: INCLUDES --------------------------------- --<br> 11 <br> 12 SET _LIB_=PATH\TO\LIBRARIES\LIBNAME.BAT<br> 13 <br> 14 :: DEFINES --------------------------------- --<br> 15 :: VARIABLES --------------------------------- --<br> 16 :: MACROS --------------------------------- --<br> 17 <br> 18 GOTO :MAINLINE<br> 19 <br> 20 :: FUNCTIONS --------------------------------- --<br> 21 :: MAINLINE --------------------------------- --<br> 22 :MAINLINE<br> 23 <br> 24 call %_LIB_% header foo<br> 25 call %_LIB_% trailer<br> 26 <br> 27 ENDLOCAL & POPD<br> 28 :: HISTORY ------------------------------------<br> 29 :: $Log$<br> 30 :: END OF FILE --------------------------------- --<br> <br>
第12行“进口”“库”…实际上它只是使后续调用更容易的语法糖…