Можно ли встраивать и выполнять VBScript в пакетном файле без использования временного файла?

Люди долгое время встраивают и выполняют VBScript в пакетных файлах. Но все опубликованные решения, которые я видел (в то время, когда этот вопрос был первоначально поставлен), включали в себя запись временного файла VBS. Например: Вставить VBScript внутри командного файла Windows .

Возможно ли выполнить встроенный VBScript внутри пакета без записи временного файла?

Примечание. Перейдите в раздел UPDATE 2014-04-27 в нижней части этого ответа для лучшего решения.

Раньше я думал, что ответа нет. Но затем пользователь DosTips Liviu обнаружил, что символ (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. Но они, кажется, были потеряны из этого поста, и я не могу понять, как их публиковать. Я заменил символы строкой

 ::echo This will execute in batch, but it will fail as vbs. remecho This will execute in batch, and it is also a valid vbs comment ::'echo This will execute in batch and it is also a valid vbs comment 

Это ключ к успешному гибриду batch / vbs. Пока каждой команде пакета предшествует rem или ::' , тогда движок vbs его не увидит, но команда пакета будет запущена. Просто убедитесь, что вы завершаете пакетную часть с помощью EXIT или EXIT /B Тогда остальная часть скрипта может быть обычным vbs.

При необходимости вы можете даже иметь пакетную метку. :'Label является действительным комментарием vbs и допустимым ярлыком пакета.

Вот тривиальный гибридный сценарий. (снова с помощью вместо встроенного символа Ctrl-Z)

 ::'@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's 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 есть большой compilation гибридов js / vbs / html / hta и химер в cmd / bat . Много хороших вещей от разных людей.

Внутри этой темы пользователь DosTips Liviu обнаружил красивое гибридное VBS / пакетное решение, которое использует WSF.

   

Я думаю, что это решение является фантастическим. Секции партии и WSF четко разделены хорошими заголовками. Код партии абсолютно нормальный, без какого-либо нечетного синтаксиса. Единственное ограничение заключается в том, что пакетный код не может содержать --> .

Точно так же код VBS в WSF абсолютно нормальный. Единственное ограничение - код VBS не может содержать .

Единственный риск - недокументированное использование "%~f0?.wsf" в качестве сценария для загрузки. Каким-то образом парсер правильно находит и загружает запущенный .BAT-скрипт "%~f0" , а суффикс ?.wsf загадочно инструктирует CSCRIPT интерпретировать сценарий как WSF. Надеюсь, MicroSoft никогда не отключит эту функцию.

Поскольку решение использует WSF, пакетный скрипт может содержать любое количество независимых VBS, JScript или других заданий, которые могут быть выборочно вызваны. Каждая работа может даже использовать несколько языков.

            

EDIT: Мой первый ответ был неправильным для VBScript, теперь моя следующая попытка …

Приятная идея использовать CTRL-Z, но мне не нравятся контрольные символы в пакетном файле, так как это сложно скопировать и вставить.
Это зависит от вашего браузера, вашего редактора, вашего …

Вы можете получить гибридный VBScript / Batch также с обычными символами и «нормальным» кодом.

 :'VBS/Batch Hybrid : : :'Makes the next line only visible for VBScript ^ a=1_ <1' echo off  

Хитрость заключается в том, чтобы добавить каждую строку партии с set n=n'& она легальна для обоих, но vbs игнорирует остальную часть строки, только партия будет выполнять оставшуюся часть строки.

Другой вариант :'remark ^ , это замечание для обоих, но для партии это замечание также является следующей строкой многострочного символа.
VbScript видит тогда a=1<1 остальная часть строки - это замечание '
Пакет видит только <1' echo off , первый переадресация с 1' будет переопределяться вторым , поэтому он приведет только к echo off < nul .

Единственная оставшаяся проблема заключается в том, что вы можете увидеть первое echo off , так как оно не работает в пакетном режиме, чтобы использовать @ после перенаправления.

Для JScript существует более простое решение для гибридных сценариев

И моя попытка ( впервые размещенная здесь ). Она похожа на решение jeb, но (по крайней мере, по мне) код более читабельен:

 :sub echo(str) :end sub echo off '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul '& echo/ '& cscript /nologo /E:vbscript %~f0 '& echo/ '& echo BATCH: Translation is at best an ECHO. '& echo/ '& pause '& rem del /q "%windir%\System32\'.exe" '& exit /b WScript.Echo "VBScript: Remorse is the ECHO of a lost virtue." WScript.Quit 

И объяснение:

  1. (одиночная кавычка) не является запрещенным символом как часть имени файла в windowsх, поэтому нет проблем с файлом с именем '.exe
  2. Есть несколько команд, заполненных windowsми, которые ничего не делают без параметров командной строки. Самые быстрые (при выполнении ничего) и большинство света в качестве размера (по моим тестам) являются subst.exe и doskey.exe
  3. Поэтому в первой строке я doskey.exe на '.exe (если он еще не существует), а затем продолжайте использовать его как '& (поскольку расширение .exe должно быть в % PATHEXT% ). Это будет сделанный как комментарий в VBScript, и в пакете ничего не сделает – просто продолжит следующую команду в строке.

Конечно, есть некоторые недостатки. По крайней мере, для первого запуска в конечном итоге вам понадобятся права администратора, так как вам может быть отказано в работе в %windir%\System32\ Для надежности вы также можете использовать '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe .\'.exe >nul '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe .\'.exe >nul а затем в конце: '& rem del /q .\'.exe

Если '.exe оставлен на вашем пути, вы могли бы использовать его ненадлежащим образом, и выполнение в каждой строке «.exe» в конечном итоге могло бы снизить производительность.

..И в командах частичной партии команды должны быть только в одной строке.

Обновление 9.10.13 (… следуя вышеприведенной конвенции)

Вот еще один способ, который требует самостоятельного переименования командного файла:

 @echo off goto :skip_xml_comment       

И короткое объяснение:

  1. Когда пакет автоматически переименовывается и переименовывается со старым именем, и это делается в одной строке (или в скобках), скрипт будет выполнен без ошибок. В этом случае добавляется также один вызов CSCRIPT.EXE с .WSF WSF.Self-переименование немного рискованно, но быстрее, чем временный файл.
  2. Хост сценария Windows не сильно заботится о элементах за пределами XML-данных, если нет специальных символов xml & < > ; поэтому @echo off и goto можно использовать без забот. Но для безопасности полезно добавлять командные команды в раздел комментария xml (или CDATA). Чтобы избежать сообщений об ошибках из пакета, я пропустил

    Я попытался собрать все решения в одном скрипте по адресу http://www.dostips.com/forum/viewtopic.php?p=37780#p37780 .

    Существует пакетный скрипт, преобразующий самые популярные языки в пакетный файл ( .js , .vbs , .ps1 , .wsf , .hta и исторический .pl ).

    Он работает следующим образом:

         :: convert filename1.vbs для исполняемого файла filename1.bat
         cmdize.bat имя_файла1.vbs
    
    
  3. Для решения этой проблемы очень простое решение. Просто используйте альтернативный stream данных (ADS) для хранения кода VBS. Чтобы просто объяснить это, ADS – это еще одно место, где вы можете хранить другие данные в одном файле , то есть файл состоит из его исходных данных и любого количества дополнительных ADS . Каждый ADS идентифицируется, отделяя свое имя от исходного имени файла через двоеточие. Например:

     test.bat <- a file called "test.bat" test.bat:script_.vbs <- an ADS of file "test.bat" called "script_.vbs" 

    Вы можете найти более техничное и подробное описание ADS в Интернете, но сейчас важно упомянуть, что эта функция работает только на дисках NTFS. Теперь давайте посмотрим, как использовать эту функцию для решения этой конкретной проблемы.

    Сначала создайте исходный пакетный файл обычным способом. Вы также можете запустить notepad.exe из командной строки следующим образом:

     notepad test.bat 

    Для моего примера я вставил следующие строки в test.bat :

     @echo off setlocal For /f "delims=" %%i in ('Cscript //nologo "test.bat:script_.vbs" "Select a folder"') do Set "folder=%%i" echo Result: "%folder%" 

    Обратите внимание на имя сценария VBS. После того, как test.bat был сохранен и Блокнот закрыт, создайте скрипт VBS с помощью Блокнота, поэтому введите эту команду в командной строке:

     notepad test.bat:script_.vbs 

    И создайте сценарий обычным способом:

     Dim objFolder, objShell Set objShell = CreateObject("Shell.Application") Set objFolder = objShell.BrowseForFolder(0, "Select a folder.", &H4000, 0) If Not (objFolder Is Nothing) Then wscript.echo objFolder.Self.path Else wscript.echo 0 End If 

    Сохраните этот файл и запустите test.bat . Оно работает! ;)

    Вы можете просмотреть файлы test.bat ADS с помощью переключателя /R в команде dir . Вы можете прочитать более подробное объяснение этого метода и его ограничений на этом посту .

  4. Поиск текста на веб-страницах с указанием списка URL-адресов
  5. VBScript & Access MDB - 800A0E7A - «Поставщик не найден. Возможно, он неправильно установлен "
  6. Как найти окно Заголовок активного (переднего плана) windows с помощью Window Script Host
  7. Чтение и запись двоичного файла в VBscript
  8. Отсоедините командную строку объема тома usb
  9. VBS: выберите один файл в папке
  10. Ошибка ввода: нет никакого механизма сценария для расширения файла ".vbs"
  11. Ошибка ASP 0177: 8007007e Ошибка сервера.CreateObject для COM-библиотеки DLL
  12. Сложные запросы wmi с использованием execquery
  13. Как разрешить запуск скриптов VB на учетной записи администратора
  14. Запуск командной строки молча с помощью VbScript и получение вывода?
Давайте будем гением компьютера.