Ответ 1
Примечание. Перейдите в раздел UPDATE 2014-04-27 в нижней части этого ответа для лучшего решения.
Раньше я думал, что ответа нет. Но затем пользователь DosTips Liviu обнаружил, что символ <SUB>
(Ctrl-Z, 0x1A, decimal 26) имеет эффекты bizare при встраивании в пакетный файл. Если функции несколько похожи на терминатор строк, так что командные команды, которые следуют за REM (или :: примечанием хаком), могут выполняться, если им предшествует Ctrl-Z. http://www.dostips.com/forum/viewtopic.php?p=13160#p13160
Это было подтверждено на XP Home Edition sp3, Vista Home Premium sp2 64 бит и Vista Enterprise sp2 32 бит. Я предполагаю, что он работает с другими версиями Windows.
Примечание. Приведенный ниже код должен иметь встроенные символы Ctrl-Z. Клянусь, я видел их на этом сайте при просмотре с помощью IE8. Но они, кажется, были потеряны из этого поста, и я не могу понять, как их публиковать. Я заменил символы строкой <SUB>
::<sub>echo This will execute in batch, but it will fail as vbs.
rem<SUB>echo This will execute in batch, and it is also a valid vbs comment
::'<SUB>echo This will execute in batch and it is also a valid vbs comment
Это ключ к успешному гибриду batch/vbs. Пока каждой команде пакета предшествует rem<SUB>
или ::'<SUB>
, тогда движок vbs его не увидит, но команда пакета будет запущена. Просто убедитесь, что вы завершаете пакетную часть с помощью EXIT
или EXIT/B
Тогда остальная часть скрипта может быть обычным vbs.
При необходимости вы можете даже иметь пакетную метку. :'Label
является действительным комментарием vbs и допустимым ярлыком пакета.
Вот тривиальный гибридный сценарий. (снова с помощью <SUB>
вместо встроенного символа Ctrl-Z)
::'<SUB>@cscript //nologo //e:vbscript "%~f0" & exit /b
WScript.Echo "Example of a hybrid VBS / batch file"
Обновление 2012-04-15
jeb нашел решение, которое позволяет избежать неудобного CTRL-Z, но он печатает ECHO OFF в начале и также устанавливает некоторые посторонние переменные.
Я нашел решение без CTRL-Z, которое устраняет посторонние переменные и проще понять.
Обычно специальные символы &
, |
, <
, >
и т.д. не работают после инструкции REM
в пакете. Но специальные персонажи работают после REM.
, Я нашел этот самородок информации по адресу http://www.dostips.com/forum/viewtopic.php?p=3500#p3500. Тест показывает, что REM.
по-прежнему является действительным комментарием VBS. EDIT - основанный на комментарии jeb, безопаснее использовать REM^
(после каретки есть пробел).
Итак, вот тривиальный гибрид VBS/batch, использующий REM^ &
. Единственным недостатком является то, что он печатает REM &
в начале, тогда как решение jeb печатает ECHO OFF
.
rem^ &@cscript //nologo //e:vbscript "%~f0" & exit /b
WScript.Echo "Example of a hybrid VBS / batch file"
Вот еще один тривиальный пример, демонстрирующий несколько командных команд, включая CALL для помеченной подпрограммы.
::' VBS/Batch Hybrid
::' --- Batch portion ---------
rem^ &@echo off
rem^ &call :'sub
rem^ &exit /b
:'sub
rem^ &echo begin batch
rem^ &cscript //nologo //e:vbscript "%~f0"
rem^ &echo end batch
rem^ &exit /b
'----- VBS portion ------------
wscript.echo "begin VBS"
wscript.echo "end VBS"
'wscript.quit(0)
Мне все еще нравится решение CTRL-Z, потому что оно устраняет все посторонние выходы.
ОБНОВЛЕНИЕ 2012-12-17
Том Лаведас опубликовал метод для удобного запуска динамического VBS из пакетного сценария в группах Google: нет гибридных сценариев VBS. В методе используется mshta.exe(Microsoft HTML Application Host).
Его оригинальное пакетное решение полагалось на внешний небольшой скрипт VBS.BAT для выполнения VBS в FOR/F. Я немного модифицировал синтаксис, чтобы сделать его удобным для встраивания непосредственно в любой заданный пакетный скрипт.
Это довольно медленно, но очень удобно. Он ограничен исполнением одной строки VBS.
VBS записывается нормально, за исключением того, что все кавычки должны быть удвоены: цитата, содержащая строку, должна быть записана как ""
, а кавычки внутри строки должны быть записаны как """"
. Обычно мини-скрипт выполняется внутри предложения IN() FOR/F. Он может выполняться напрямую, но только если stdout был перенаправлен или передан по каналам.
Он должен работать с любой ОС Windows с XP до тех пор, пока установлен IE.
@echo off
setlocal
:: Define simple batch "macros" to implement VBS within batch
set "vbsBegin=mshta vbscript:Execute("createobject(""scripting.filesystemobject"")"
set "vbsBegin=%vbsBegin%.GetStandardStream(1).write("
set ^"vbsEnd=):close"^)"
:: Get yesterday date
for /f %%Y in ('%vbsBegin% date-1 %vbsEnd%') do set Yesterday=%%Y
set Yesterday
pause
echo(
:: Get pi
for /f %%P in ('%vbsBegin% 4*atn(1) %vbsEnd%') do set PI=%%P
set PI
pause
echo(
set "var=name=value"
echo Before - %var%
:: Replace =
for /f "delims=" %%S in (
'%vbsBegin% replace(""%var%"",""="","": "") %vbsEnd%'
) do set "var=%%S"
echo After - %var%
pause
echo(
echo Extended ASCII:
for /l %%N in (0,1,255) do (
%= Get extended ASCII char, except can't work for 0x00, 0x0A. =%
%= Quotes are only needed for 0x0D =%
%= Enclosing string quote must be coded as "" =%
%= Internal string quote must be coded as """" =%
for /f delims^=^ eol^= %%C in (
'%vbsBegin% """"""""+chr(%%N)+"""""""" %vbsEnd%'
) do set "char.%%N=%%~C"
%= Display result =%
if defined char.%%N (
setlocal enableDelayedExpansion
echo( %%N: [ !char.%%N! ]
endlocal
) else echo( %%N: Doesn't work :(
)
pause
echo(
:: Executing the mini VBS script directly like the commented code below
:: will not work because mshta fails unless stdout has been redirected
:: or piped.
::
:: %vbsBegin% ""Hello world"" %vbsEnd%
::
:: But this works because output has been piped
%vbsBegin% ""Hello world"" %vbsEnd% | findstr "^"
pause
ОБНОВЛЕНИЕ 2014-04-27
В DosTips есть большой сборник гибридов js/vbs/html/hta и химер в cmd/bat. Много хороших вещей от разных людей.
Внутри этой темы пользователь DosTips Liviu обнаружил красивое гибридное VBS/пакетное решение, которое использует WSF.
<!-- : Begin batch script
@echo off
cscript //nologo "%~f0?.wsf"
exit /b
----- Begin wsf script --->
<job><script language="VBScript">
WScript.Echo "VBScript output called by batch"
</script></job>
Я думаю, что это решение является фантастическим. Секции партии и WSF четко разделены хорошими заголовками. Код партии абсолютно нормальный, без какого-либо нечетного синтаксиса. Единственное ограничение заключается в том, что пакетный код не может содержать -->
.
Точно так же код VBS в WSF абсолютно нормальный. Единственное ограничение - код VBS не может содержать </script>
.
Единственный риск - недокументированное использование "%~f0?.wsf"
в качестве сценария для загрузки. Каким-то образом парсер правильно находит и загружает запущенный.BAT-скрипт "%~f0"
, а суффикс ?.wsf
загадочно инструктирует CSCRIPT интерпретировать сценарий как WSF. Надеюсь, MicroSoft никогда не отключит эту функцию.
Поскольку решение использует WSF, пакетный скрипт может содержать любое количество независимых VBS, JScript или других заданий, которые могут быть выборочно вызваны. Каждая работа может даже использовать несколько языков.
<!-- : Begin batch script
@echo off
echo batch output
cscript //nologo "%~f0?.wsf" //job:JS
cscript //nologo "%~f0?.wsf" //job:VBS
exit /b
----- Begin wsf script --->
<package>
<job id="JS">
<script language="VBScript">
sub vbsEcho()
WScript.Echo "VBScript output called by JScript called by batch"
end sub
</script>
<script language="JScript">
WScript.Echo("JScript output called by batch");
vbsEcho();
</script>
</job>
<job id="VBS">
<script language="JScript">
function jsEcho() {
WScript.Echo("JScript output called by VBScript called by batch");
}
</script>
<script language="VBScript">
WScript.Echo "VBScript output called by batch"
call jsEcho
</script>
</job>
</package>