Библиотека функций Windows .bat / .cmd в собственном файле? - PullRequest
13 голосов
/ 10 октября 2011

есть хороший способ для создания функций в сценарии DOS .bat / .cmd.Чтобы модулировать некоторые установочные сценарии, было бы неплохо включить файл с библиотекой функций в сценарий .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.

Что означает более или менее: Не удается найти точку перехода с именем function1

Есть идеи или это невозможно?

Ответы [ 5 ]

12 голосов
/ 10 октября 2011

Это возможно, и есть несколько разных способов сделать это.

1) Скопируйте и вставьте полную «Библиотеку» в каждый из ваших файлов Работает, но на самом деле это не библиотека, и ужасает изменение / исправление библиотечной функции во всех файлах

2) включить библиотеку через call-wrapper

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=,
1 голос
/ 23 мая 2015

Я предложил простое решение для использования внешних библиотек с пакетными файлами, и я хотел бы попросить вас, ребята, протестировать его и найти возможные ошибки.

Как использовать:

  • Создать библиотеку (папку с пакетными файлами библиотеки внутри)
  • Поместите этот заголовок перед любым создаваемым вами пакетным файлом, использующим библиотеку.

Принцип действия:

  • Создает временный файл с библиотеками, скопированными в конец файла.Он ищет библиотеки по всем путям, перечисленным в% _IncludePath%.
  • Чтобы это работало, библиотеки должны быть в «функциональной» структуре.Библиотеки примеров можно найти по адресу: http://www.commandline.co.uk/lib/treeview/index.php?contents.php&../treeview/main.php

Как это работает:

  • Создает временный файл с% TEMP% (не работает, если% TEMP%не задано)
  • Копирует себя в этот временный файл
  • Выполняет поиск каждой библиотеки по следующим путям:
    • исходный путь к пакетному файлу
    • % BatchLibraryPath%
    • Любой другой путь, указанный в% _IncludePath%
  • Добавляет эти библиотеки во временный файл
  • Запускает временный файл
  • , завершает работу и удаляетвременный файл

Преимущества:

  • Переданные аргументы командной строки работают отлично
  • Нет необходимости завершать код пользователя какой-либо специальной командой
  • Библиотеки могут находиться где угодно на компьютере
  • Библиотеки могут находиться в общих папках с путями UNC
  • Библиотеки могут быть расположены по разным путям, и все они будут добавлены (если одна и та же библиотека найдена вразные пути, тот самый левый путь в% _IncludePath%used)
  • Возвращает уровень ошибки в случае возникновения ошибки

Код:

  • Вот пример: чтобы это работало, у вас должен быть файл Example.batбиблиотека в папке Your_batch_file.bat (или в одной из папок% _IncludePath%)

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%, просто поместите этот файл внутрипуть к вашей библиотеке и запустите его перед запуском Your_batch_file.bat.Этот параметр остается постоянным при перезагрузке, поэтому вы запускаете его только один раз:

SetBatchLibraryPath.bat

setx BatchLibraryPath "%~dp0"
pause
1 голос
/ 13 октября 2011

Существует более простой способ загружать библиотечные функции каждый раз, когда выполняется основной файл. Например:

@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 голосов
/ 29 апреля 2016

хорошо ... быстро и грязно, потому что я парень из 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 ^&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>

это должно быть довольно просто для тебя ... в строке 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 "импортирует "библиотеку" ... на самом деле это просто синтаксический сахар, который облегчает последующие вызовы ...

0 голосов
/ 15 октября 2013

Другим решением будет временное добавление библиотечных функций к исполняемому пакетному файлу.

Исходный файл может быть сохранен во временном файле до изменения и восстановлен после завершения. Это имеет обратную сторону: вам нужно вызвать функцию: 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...