【发布时间】:2013-03-01 22:12:49
【问题描述】:
我有一个简单的问题:
从 Windows 批处理 (.bat) 脚本执行单个 WshShell 命令的最佳方法是什么?
(希望不是用 VB 代码创建新文件)
【问题讨论】:
标签: windows batch-file wsh
我有一个简单的问题:
从 Windows 批处理 (.bat) 脚本执行单个 WshShell 命令的最佳方法是什么?
(希望不是用 VB 代码创建新文件)
【问题讨论】:
标签: windows batch-file wsh
您可以通过 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 将第一行视为一个简单的 IF 命令,该命令的计算结果始终为 false,因此它永远不会执行不存在的 @end 命令,也不会造成任何伤害。以下行都是正常的批处理代码,直到到达 exit /b,此时批处理终止并忽略其余行。
JScript 将第一行视为一个空的条件编译块,然后是多行注释的开头。 JScript 忽略以下批处理代码,因为它是注释的一部分。注释以*/ 结尾,然后是普通的JScript 代码。
唯一可能失败的情况是您的批处理代码中必须包含*/,因为这会过早终止 JScript 注释。但这可以通过在 * 和 / 之间放置一些在批量解析后消失的东西来解决。如果代码没有被引用,那么您可以简单地转义斜杠,如下所示:*^/。如果代码被引用,那么您可以扩展一个未定义的变量:*%=%/。保证不会定义名为 = 的变量。
【讨论】:
这是我用来编写 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 之后关闭(*/)。
【讨论】:
感谢以上内容启发我做一些细微的修改。
@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)
【讨论】:
你也可以使用这个适用于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")
【讨论】: