我有一个简单的问题:
从Windows批处理(.bat)脚本执行单个WshShell命令的最佳方法是什么?
(希望它不是用VB代码创建新文件)
答案 0 :(得分:7)
您可以通过VBScript或Jscript访问WshShell。两者都可以嵌入批处理文件中,但JScript更清晰。
大多数人通过编写临时VBS文件来批量执行VBScript。但是没有临时文件就可以做到这一点。有关各种选项,请参阅Is it possible to embed and execute VBScript within a batch file without using a temporary file?。
在批处理中嵌入JScript非常简单。见https://stackoverflow.com/a/5656250/1012053。我使用了这种技术的一个非常小的变化。
@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和批处理的有效语法的行。
Batch将第一行看作一个总是求值为false的简单IF命令,因此它永远不会执行不存在的@end命令,并且不会造成任何损害。在达到exit / b之前,以下行都是正常的批处理代码,此时批处理将终止,其余行将被忽略。
JScript将第一行视为空条件编译块,然后是多行注释的开头。 JScript忽略以下批处理代码,因为它是注释的全部内容。注释以*/
结尾,然后是普通的JScript代码。
唯一可能失败的是您的批处理代码中必须包含*/
,因为这会过早终止JScript注释。但这可以通过在批量解析后消失的*
和/
之间放置一些东西来解决。如果未引用代码,则可以按如下方式转义斜杠:*^/
。如果引用了代码,则可以展开未定义的变量:*%=%/
。保证名为=
的变量不被定义。
答案 1 :(得分:7)
这是我用来编写Batch-JScript混合脚本的方法:
@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
编辑:如果您想要更简单/更短的方法,请使用以下方法:
@set @a=0 /*
@cscript //nologo //E:JScript "%~F0" "%~1"
@goto :EOF */
WScript.Echo(eval(WScript.Arguments(0)));
同样,第一个@set @a=0 /*
是JScript和Batch中的有效语句/命令,仅用于插入JScript注释(/ *)的开头,因此JScript会忽略Batch部分。评论在最终goto :EOF
之后关闭(* /)。
答案 2 :(得分:1)
感谢上面的鼓励我做一些修改。
@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)
答案 3 :(得分:0)
您还可以使用适用于node.js的此方法:
0</* ::
@echo off
echo hello from batch
rem -- CALLING NODE
::node "%~f0" %*
rem -- CALLING CSCRIPT
cscript //E:JScript //nologo "%~f0" %*
exit /b %errorlevel%
*/0;
// -- NODE CODE
//console.log('Hello from Node');
// -- JScript CODE
WScript.Echo("Hello from JSCript")