是否可以在不使用临时文件的情况下在批处理文件中嵌入和执行 VBScript? [英] Is it possible to embed and execute VBScript within a batch file without using a temporary file?

查看:26
本文介绍了是否可以在不使用临时文件的情况下在批处理文件中嵌入和执行 VBScript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

人们长期以来一直在批处理文件中嵌入和执行 VBScript.但是我看到的所有已发布的解决方案(在最初提出这个问题时) 都涉及编写一个临时 VBS 文件.例如:在 Windows 批处理文件中嵌入 VBScript.

People have been embedding and executing VBScript within batch files for a long time. But all the published solutions that I have seen (at the time this question was originally posed) involve writing a temporary VBS file. For example: Embed VBScript inside Windows batch file.

是否可以在不写入临时文件的情况下批量执行嵌入的 VBScript?

Is it possible to execute embedded VBScript within batch without writing a temporary file?

推荐答案

注意 - 跳转到 UPDATE 2014-04-27 此答案底部的部分以获得最佳解决方案.

我曾经认为答案是否定的.但是 DosTips 用户 Liviu 发现 <SUB> 字符(Ctrl-Z,0x1A,十进制 26)在嵌入批处理文件时会产生奇怪的效果.If 的功能有点像行终止符,这样在 REM(或 :: remark hack)之后的批处理命令可以执行,如果它们前面是 Ctrl-Z.http://www.dostips.com/forum/viewtopic.php?p=13160#p13160

I used to think the answer was no. But then DosTips user Liviu discovered that the <SUB> character (Ctrl-Z, 0x1A, decimal 26) has bizare effects when embedded within a batch file. If functions somewhat like a line terminator such that it is possible for batch commands that follow a REM (or a :: remark hack) to execute if they are preceded by 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 版本.

This has been confirmed on XP Home Edition sp3, Vista Home Premium sp2 64 bit, and Vista Enterprise sp2 32 bit. I'm assuming it works on other Windows versions.

注意 - 下面的代码应该嵌入了 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

这是成功的批处理/vbs 混合的关键.只要每个批处理命令前面都有rem::',那么vbs引擎就看不到了,但是批处理命令会跑.只需确保使用 EXITEXIT/B 终止批处理部分.然后脚本的其余部分可以是正常的 vbs.

That is the key to a successful batch/vbs hybrid. As long as each batch command is preceded by rem<SUB> or ::'<SUB>, then the vbs engine won't see it, but the batch command will run. Just make sure you terminate the batch portion with an EXIT or EXIT /B. Then the remainder of the script can be normal looking vbs.

如果需要,您甚至可以拥有批次标签.:'Label 既是有效的 vbs 注释,也是有效的批标签.

You can even have a batch label if needed. :'Label is both a valid vbs comment and a valid batch label.

这是一个简单的混合脚本.(再次用 代替嵌入的 Ctrl-Z 字符)

Here is a trivial hybrid script. (again with <SUB> in place of embedded Ctrl-Z char)

::'<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 并且还设置了一些无关变量.

jeb found a solution that avoids the awkward CTRL-Z, but it prints out ECHO OFF at the start and also sets some extraneous variables.

我找到了一个没有 CTRL-Z 的解决方案,它消除了无关变量并且更容易理解.

I have found a solution without CTRL-Z that eliminates the extraneous variables and is simpler to comprehend.

通常特殊字符&|<> 等等.在批处理 REM 语句之后工作.但是特殊字符在 REM. 之后确实有效.我在 http://www.dostips.com/论坛/viewtopic.php?p=3500#p3500.测试表明 REM. 仍然是有效的 VBS 注释.EDIT -基于jeb的评论,使用REM^更安全(插入符号后有一个空格).

Normally the special characters &, |, <, > etc. don't work after a REM statement in batch. But the special characters do work after REM.. I found this nugget of information at http://www.dostips.com/forum/viewtopic.php?p=3500#p3500. A test shows that REM. is still a valid VBS comment. EDIT - based on jeb's comment, it is safer to use REM^ (there is a space after the caret).

所以这是一个使用 REM^ & 的简单 VBS/批处理混合.唯一的缺点是它在开头打印 REM &,而 jeb 的解决方案打印 ECHO OFF.

So here is a trivial VBS/batch hybrid using REM^ &. The only drawback is it prints REM & at the beginning, whereas jeb's solution prints ECHO OFF.

rem^ &@cscript //nologo //e:vbscript "%~f0" & exit /b
WScript.Echo "Example of a hybrid VBS / batch file"

这是另一个简单的示例,它演示了多个批处理命令,包括对标记子例程的调用.

Here is another trivial example that demonstrates multiple batch commands, including a CALL to a labeled sub-routine.

::' 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 解决方案,因为它消除了所有无关输出.

I still like the CTRL-Z solution because it eliminates all extraneous output.

更新 2012-12-17

Tom Lavedas 在 Google Groups 上发布了一种从批处理脚本中方便地运行动态 VBS 的方法:无文件 VBS 混合脚本.该方法使用mshta.exe(Microsoft HTML Application Host).

Tom Lavedas posted a method to conveniently run dynamic VBS from a batch script over at Google Groups: No file VBS hybrid scripting. The method uses mshta.exe (Microsoft HTML Application Host).

他最初的批处理解决方案依赖于外部小型 VBS.BAT 脚本在 FOR/F 内执行 VBS.我稍微修改了语法,以便可以方便地直接嵌入到任何给定的批处理脚本中.

His original batch solution relied on an external small VBS.BAT script to execute the VBS within a FOR /F. I modified the syntax slightly to make it convenient to embed directly within any given batch script.

速度很慢,但是很方便.仅限于执行单行 VBS.

It is quite slow, but very convenient. It is restricted to executing a single line of VBS.

VBS 是正常书写的,除了所有引号都必须加倍:包含字符串的引号必须写为 "",字符串内部的引号必须写为 """".通常,迷你脚本在 FOR/F 的 IN() 子句中执行.它可以直接执行,但前提是 stdout 已被重定向或管道传输.

The VBS is written normally, except all quotes must be doubled: A quote enclosing a string must be written as "", and quotes internal to a string must be written as """". Normally the mini script is executed within the IN() clause of a FOR /F. It can be executed directly, but only if stdout has been redirected or piped.

只要安装了 IE,它就可以在 XP 以后的任何 Windows 操作系统上运行.

It should work on any Windows OS from XP onward as long as IE is installed.

@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 上有一个很好的 js/vbs 纲要/html/hta 混合体和 cmd/bat 中的嵌合体.很多来自不同人的好东西.

Over at DosTips there is a great compendium of js/vbs/html/hta hybrids and chimeras in cmd/bat. Lots of good stuff from various people.

在该线程中,DosTips 用户 Liviu 发现了一个漂亮的 VBS/批处理混合 使用 WSF 的解决方案.

Within that thread, DosTips user Liviu discovered a beautiful VBS/batch hybrid solution that uses 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 部分由漂亮的标题清楚地分开.批处理代码绝对正常,没有任何奇怪的语法.唯一的限制是批号不能包含-->.

I think this solution is fantastic. The batch and WSF sections are clearly separated by nice headers. The batch code is absolutely normal, without any odd syntax. The only restriction is the batch code cannot contain -->.

同样,WSF内的VBS代码也是绝对正常的.唯一的限制是 VBS 代码不能包含 .

Similarly, the VBS code within WSF is absolutely normal. The only restriction is the VBS code cannot contain </script>.

唯一的风险是未公开使用 "%~f0?.wsf" 作为要加载的脚本.解析器以某种方式正确地找到并加载正在运行的 .BAT 脚本 "%~f0",并且 ?.wsf 后缀神秘地指示 CSCRIPT 将脚本解释为 WSF.希望微软永远不会禁用那个功能".

The only risk is the undocumented use of "%~f0?.wsf" as the script to load. Somehow the parser properly finds and loads the running .BAT script "%~f0", and the ?.wsf suffix mysteriously instructs CSCRIPT to interpret the script as WSF. Hopefully MicroSoft will never disable that "feature".

由于解决方案使用 WSF,批处理脚本可以包含任意数量的独立 VBS、JScript 或其他可以选择性调用的作业.每个工作甚至可以使用多种语言.

Since the solution uses WSF, the batch script can contain any number of independent VBS, JScript, or other jobs that can be selectively called. Each job can even utilize multiple languages.

<!-- : 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>

这篇关于是否可以在不使用临时文件的情况下在批处理文件中嵌入和执行 VBScript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆