У меня есть простой вопрос:
Какой лучший способ выполнить одну команду WshShell из пакета Windows (.bat) script?
(надеюсь, что он не создает новый файл с кодом VB)
У меня есть простой вопрос:
Какой лучший способ выполнить одну команду WshShell из пакета Windows (.bat) script?
(надеюсь, что он не создает новый файл с кодом VB)
Вы можете получить доступ к WshShell через VBScript или Jscript. Оба могут быть встроены в пакетный файл, но JScript намного чище.
Большинство людей выполняют VBScript внутри пакета, записывая временный файл VBS. Но это можно сделать без временного файла. См. Возможно ли внедрить и выполнить VBScript в пакетном файле без использования временного файла? для различных опций.
Встраивание JScript в пакетном режиме довольно просто. См. fooobar.com/questions/7983/.... Я использую очень небольшое изменение этой техники.
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: ******* Begin batch code *********
@echo off
:: Your batch logic goes here
:: At any point you can execute the following to access your JScript
cscript //E:JScript //nologo "%~f0" yourJscriptParametersGoHere
:: Be sure to terminate your script so that
:: it does not fall through into the JScript code
exit /b
********* Begin JScript code **********/
var WshShell=WScript.CreateObject("WScript.Shell")
/* do whatever with your WshShell object */
Пояснение:
Ключом к технике является первая строка. Это должна быть строка, которая имеет действительный синтаксис как для JScript, так и для пакета.
Пакет видит первую строку как простую команду IF, которая всегда оценивает значение false, поэтому никогда не выполняет несуществующую команду @end, и никакого вреда не делается. Следующие строки представляют собой нормальный пакетный код до тех пор, пока не будет достигнут выход /b, после чего завершается пакетная обработка, а оставшиеся строки игнорируются.
JScript видит первую строку как пустой блок условной компиляции, за которым следует начало многострочного комментария. JScript игнорирует следующий пакетный код, потому что он является частью комментария. Комментарий заканчивается на */
, а затем появляется нормальный код JScript.
Единственное, что может потерпеть неудачу, - это то, что ваш пакетный код должен иметь */
внутри него, потому что это преждевременно завершит комментарий JScript. Но это можно решить, помещая что-то между *
и /
, которое исчезает после парсинга. Если код не указан, вы можете просто избежать косой черты следующим образом: *^/
. Если код цитируется, вы можете развернуть переменную undefined: *%=%/
. Переменная с именем =
гарантированно не определена.
Это метод, который я использую для написания гибридного Batch-JScript script:
@if (@CodeSection == @Batch) @then
:: The first line above is...
:: in Batch: a valid IF command that does nothing.
:: in JScript: a conditional compilation IF statement that is false,
:: so this section is omitted until next "at-sign end".
@echo off
rem EXPR.BAT: Evaluate a JScript (arithmetic) expression
rem Antonio Perez Ayala
rem Define an auxiliary variable to call JScript
set JSCall=Cscript //nologo //E:JScript "%~F0"
rem Do Batch business here, for example:
%JSCall% %1
goto :EOF
End of Batch section
@end
// JScript section
WScript.Echo(eval(WScript.Arguments.Unnamed.Item(0)));
Например:
EXPR 1/3
EDIT. Если вы хотите использовать более простой/более короткий метод, используйте этот:
@set @a=0 /*
@cscript //nologo //E:JScript "%~F0" "%~1"
@goto :EOF */
WScript.Echo(eval(WScript.Arguments(0)));
Опять же, первый @set @a=0 /*
является допустимым оператором/командой в JScript и Batch, который используется только для вставки начала комментария JScript (/*), поэтому секция Batch игнорируется JScript. Комментарий закрыт (*/) после окончательного goto :EOF
.
Спасибо за это, чтобы вдохновить меня сделать небольшую модификацию.
@if (false)==nul ======= CMD code =======
@echo off
::code before Cscript
cscript //nologo //e:jscript "%~f0" %*
echo it returns: %errorlevel%
::code after Cscript
exit /b
=================================
Freedom Land ^o^
======= J/VB Script code ======
@end
// Start Cscript
WScript.Echo("wsh says: Hello, Universe!");
WScript.Quit(123.456)