2011-10-10 28 views
12

hay a nice way to build functions en el script DOS .bat/.cmd. Para modularizar algunas secuencias de comandos de instalación, sería bueno incluir un archivo con una biblioteca de funciones en una secuencia de comandos .bat/.cmd.Biblioteca de funciones de Windows .bat/.cmd en un archivo propio?

lo que intenté fue:

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 

Cuando llamo mainscript.bat en cuando me siento siguiente resultado: Das Sprungziel - function1 wurde nicht gefunden.

Lo que significa más o menos: No se puede encontrar jump punto nombrado function1

Todas las ideas, o no es esto posible?

Respuesta

11

Es posible, y hay algunas maneras diferentes de hacerlo.

1) Copia & Pega la completa "biblioteca" en cada uno de sus archivos obras, pero en realidad no es una biblioteca, y es un horror para cambiar/corregir una función de biblioteca en todos los archivos

2) incluyen una biblioteca a través de llamada-envoltorio

call batchLib.bat :length result "abcdef" 

y batchLib.bat comienza con

call %* 
exit /b 
... 
:length 
... 

fácil de programar, pero muy sl ow, ya que cada llamada a la biblioteca carga el lote de la biblioteca y posibles problemas con los parámetros.

3) Un "auto-carga" biblioteca BatchLibrary or how to include batch files

Se crea cada vez que un archivo por lotes temporal, combinada del código de cuenta y el código de la biblioteca.
Hace algunas funciones avanzadas en el inicio de la biblioteca, como el acceso seguro a parámetros. Pero en mi opinión también es fácil de usar

Una muestra de scripts de usuario

@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% 

EDIT: Otra forma es ...

4) Una biblioteca de macros

Usted podría use macros por lotes, es fácil de incluir y usarlos.

call MacroLib.bat 

set myString=abcdef 
%$strLen% result,myString 
echo The length of myString is %result% 

¡Pero es complicado crear las macros!
Más acerca de la técnica de macro en Batch "macros" with arguments

MacroLibrary.bate

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=, 
+0

genial! Exactamente lo que estaba buscando. Definitivamente no entiendo los detalles sobre el paso de parámetros, pero lo intentaré. ¡muchas gracias! – andreas

1

Hay una forma más fácil de cargar las funciones de la biblioteca cada vez que se ejecuta el archivo principal. Por ejemplo:

@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 
+0

Voy a intentarlo también. ¡Gracias! – andreas

0

Otra solución sería adjuntar temporalmente las funciones de la biblioteca al archivo por lotes en ejecución.

El archivo original puede guardarse en un archivo temporal antes del cambio y restaurarse cuando haya terminado. Esto tiene la desventaja de que debe llamar a la función: deimport al final para restaurar el archivo y eliminar el archivo temporal. También es necesario ser capaz de escribir en el archivo por lotes y la carpeta que se encuentra actualmente.

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: \ ruta con espacios \ 2.bat lib

:LIB2TEST 
ECHO output from lib 2.bat 
GOTO:EOF 


Alternativamente utilizando la versión externa. Tenga en cuenta que esto importa la función de importación, así que asegúrese de eliminarla en el archivo 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 
1

me ocurrió una solución simple para el uso de bibliotecas externas con archivos por lotes, y me gustaría preguntarle chicos para probar y encontrar posibles errores.

Modo de empleo:

  • crear una biblioteca (una carpeta con archivos por lotes dentro de la biblioteca)
  • poner esta cabecera antes de cualquier archivo por lotes se crea que utiliza una biblioteca.

Principio de funcionamiento:

Cómo funciona:

  • crea un archivo temporal en% TEMP% (trabajo postulante no si% TEMP% no está establecido)
  • copia a sí mismo a este archivo temporal
  • Búsquedas para cada biblioteca en estos caminos:
    • ruta del archivo original del lote
    • % BatchLibraryPath%
    • Cualquier otra ruta que aparece en% _IncludesPath%
  • Anexa estas bibliotecas en el archivo temporal
  • Ejecuta el archivo temporal
  • salidas y elimina archivos temporales

Ventajas :

  • Pasó la línea de comando a rguments funcionar perfectamente
  • No hay necesidad de poner fin al código de usuario con cualquier comando especial
  • Las bibliotecas pueden estar en cualquier lugar en el equipo
  • Las bibliotecas pueden estar en carpetas compartidas con rutas UNC
  • Usted puede tener bibliotecas en diferentes rutas y todos ellos se sumarán (si misma biblioteca se encuentra en diferentes caminos, se utiliza el de más a la izquierda en la ruta% _IncludesPath%)
  • devoluciones ErrorLevel si se produce cualquier error

Código:

  • Aquí se muestra un ejemplo: para que esto funcione debe tener la biblioteca Example.bat en la carpeta Your_batch_file.bat (o en una de las carpetas% _IncludesPath%)

Your_batch_file. bate

@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 
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 

Si desea una manera fácil de establecer el% BatchLibraryPath%, sólo hay que poner este archivo dentro de su ruta de bibliotecas y ejecutarlo antes de ejecutar Your_batch_file.bat. Esta configuración es persistente en los reinicios, por lo que ejecuta esto solo una vez:

SetBatchLibraryPath.bate

setx BatchLibraryPath "%~dp0" 
pause 
0

bien ... rápida & sucia porque yo soy un tipo UNIX ... crear el archivo "biblioteca"

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 ^&lt;HTML^&gt;<br> 
21  ECHO ^&lt;HEAD^&gt;<br> 
22  ECHO ^&lt;TITLE^&gt;%1^&lt;/TITLE^&gt;<br> 
23  ECHO ^&lt;/HEAD^&gt;<br> 
24  ECHO ^&lt;BODY^&gt;<br> 
25  GOTO :EOF<br> 
26 <br> 
27 :TRAILER<br> 
28  ECHO ^&lt;/BODY^&gt;<br> 
29  ECHO ^&lt;/HTML^&gt;<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> 

este debe ser bastante recta hacia adelante para usted ... en la línea 15 hacemos el salto a la línea principal para comenzar la ejecución real. En las líneas 19 y 27 creamos puntos de entrada para nuestras rutinas. En las líneas 35 y 36 hay llamadas a las rutinas internas.

ahora, a construir el archivo que va a llamar a las rutinas de biblioteca ..

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> 

línea 12 "importaciones" la "biblioteca" ... en realidad es sólo azúcar sintáctico que hace que las llamadas posteriores más fácil ...

Cuestiones relacionadas