|
electronixtar
铂金会员
      
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『楼 主』:
[vbs]截获cmd命令输出的脚本
使用 LLM 解释/回答一下
搞了很久才发现WScript.Shell有这么好的一个功能!
Set objShell = CreateObject("WScript.Shell")
Set objExecObject = objShell.Exec ("%comspec% /c " & wscript.arguments(0))
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
loop
msgbox strText
保存为GetStdOut.vbs,在命令行里转到相应目录运行:
cscript.exe GetStdOut.vbs "ping 127.1"
看看,是不是出来了:
Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Ping statistics for 127.0.0.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
Last edited by electronixtar on 2006-6-7 at 17:19 ]
It took a long time to discover that WScript.Shell has such a great function!
Set objShell = CreateObject("WScript.Shell")
Set objExecObject = objShell.Exec ("%comspec% /c " & wscript.arguments(0))
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
loop
msgbox strText
Save it as GetStdOut.vbs, and in the command line, navigate to the corresponding directory and run:
cscript.exe GetStdOut.vbs "ping 127.1"
Look, isn't this coming out:
Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Ping statistics for 127.0.0.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
Last edited by electronixtar on 2006-6-7 at 17:19 ]
此帖被 +9 点积分 点击查看详情 评分人:【 redtek 】 | 分数: +3 | 时间:2006-11-24 14:07 | 评分人:【 lxmxn 】 | 分数: +2 | 时间:2006-12-29 00:35 | 评分人:【 jmz573515 】 | 分数: +4 | 时间:2006-12-29 04:10 |
|
|
|
2006-6-7 17:13 |
|
|
bagpipe
银牌会员
     DOS联盟捡破烂的
积分 1144
发帖 425
注册 2005-10-20 来自 北京
状态 离线
|
『第 2 楼』:
使用 LLM 解释/回答一下
其实对于vbs脚本来说管道的操作还是有一定必要的,而WSCRIPT.SHELL和用EXEC执行的管道命令的属性和方法还是有一定区别的,不过大体一样
In fact, for VBS scripts, the operation of pipes is still necessary to a certain extent. And there are certain differences between the properties and methods of WSCRIPT.SHELL and the pipe commands executed by EXEC, but they are generally the same
|
|
2006-6-7 17:41 |
|
|
electronixtar
铂金会员
      
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『第 3 楼』:
使用 LLM 解释/回答一下
BagPipe换头像和签名了啊~~~呵呵~~
BagPipe has changed the avatar and signature. Hehe~
|

C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>" |
|
2006-6-8 21:47 |
|
|
willsort
元老会员
         Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
 『第 4 楼』:
使用 LLM 解释/回答一下
Re electronixtar:
关于这个主题,下面的链接文章中讲的很详细。
引自:Microsoft TechNet:脚本漫谈--2002年10月:从WSH脚本中运行程序
http://www.microsoft.com/china/technet/archives/columns/scripts/sg1002.asp
脚本漫谈--2002年10月
从WSH脚本中运行程序
脚本专家组
脚本专家组衷心欢迎您访问我们新近开辟的这个每月一期的专栏。我们原本希望依靠自身力量创办这个专栏,但却实在力不从心。正如您所看到的,这其实根本就不是我们的专栏;而是属于您们的专栏。您们将精心编写的大量电子邮件发送至scripter@microsoft.com,而这个专栏则恰恰(并将继续)建立在您们所提供的问题和评论基础之上。正因如此,脚本专家组才得以有条不紊地欢迎大家访问属于自己的专栏;我们衷心希望您们能够在此发现既赏心悦目又具备实用价值的信息资料。如果本专栏所呈献的内容并不令您满意,则请不吝赐教!
我们所收到的较为常见一个问题就是,如何从WSH脚本中运行程序。以下是摘自此类电子邮件的一个具有代表性的片断。
你们曾在Web广播中提到过两行可帮助你们运行某一外部程序的脚本代码。请问,你们能否提供有关代码的示例样本?
作为针对上述问题的答复,我们决定占用本专栏第一期的篇幅向您介绍从自行编制的脚本中运行外部程序的具体实现方式。若问您为何需要从脚本中运行外部程序?就请这样设想:命令行工具将允许您执行一整套特定任务,而批处理脚本则提供了所需逻辑线程,以便您用来将这些任务缝合成足以构建自定义解决方案的基本要素。但是,如果批处理脚本所提供的逻辑线程尚不具备足够强大的功能,亦或构建解决方案所需必要组件不能由命令行工具提供,又将如之奈何?而这恰恰是WSH脚本大显身手的用武之地。这种脚本将允许您针对由脚本编程语言(如VBScript)所提供的强大逻辑线程加以应用,并借助强大的工具手段(如WMI和ADSI)以及命令行工具和批处理脚本将您自己的任务解决方案付诸实施。
让我们立即着手编写一个示例脚本。事实上,我们应该在编写脚本之前,先确保具备一个用来保存这个脚本的物理位置。如果在您所使用的计算机上并不存在一个名为C:\Scripts的文件夹,就请返回根目录,并新建这个文件夹。当您完成上述工作后,应打开记事本或其它文本编辑器,并键入以下脚本代码,然后,使用RunIPConfig.vbs文件名将其保存至您的C:\Scripts文件夹。
Set objShell = CreateObject(“Wscript.Shell”)
objShell.Run “ipconfig”
在尝试运行刚刚生成的脚本之前,让我们先对其进行检查,并设法事先指出可能产生的运行结果。在这个脚本中存在着两个有助于我们预测运行结果的暗示。第一行代码中包括动词Create(生成,实际上是CreateObject),而第二行代码则包含动词Run(运行)。可见,这个脚本将有可能先生成某种被称作对象的东西,并随后运行某一特定程序。事实上,情况看上去更象是该脚本将运行一个文件名为ipconfig.exe的命令行工具。
以上预测的确与该脚本所产生的运行结果相符。该脚本首先生成一种被称作对象的东西。在这个示例中,脚本所生成的对象是Shell(WshShell)对象。您可将某一对象理解成类似于命令行工具的东西;而您的脚本则可借助它执行某一特定类型的任务。Shell对象将允许您从脚本中执行原本可在Windows命令解释程序内执行的任务--就像运行程序一样。
与命令行工具不同的是,您必须在开始对其加以应用之前,先行生成一个新对象。当生成该对象时,还应为它指定一个将在脚本其余部分中被用来对它进行引用的名称。在这个示例中,我们所使用的名称是objShell。当对象生成完毕并被赋予相关名称后,我们便可利用该对象执行相关任务,具体方法为:在对象名后加上一个圆点(.),并在圆点后加上所需完成的任务名称。这个例子中的任务名是Run。而Run则是众所周知的Shell对象方法。
现在,请打开一个命令行窗体,并导航至C:\Scripts文件夹。如需运行您刚刚编写的脚本,则请输入cscript RunIPConfig.vbs命令,并按回车键。您将看到一个窗体在屏幕上一闪而过,但该窗体所显示的内容却在您能够看清之前消失了!您可反复尝试运行该脚本,并试图破解消失在窗体中的信息。这也许是一件饶有兴味的事,但却可通过一种更加简便的方法完成。
为了便于您进行理解,我们必须针对在您运行命令行工具的同时所发生的事件给予关注。当您在命令行方式下输入ipconfig、并在键盘上敲击回车键时,便对命令解释程序发出了一个指令。而命令解释程序则将对您所输入的指令进行检查。如果您所输入的命令代表着一个有效程序,那么,命令解释程序便会为您运行该程序。如果您所输入的命令并不代表有效程序,那么,命令解释程序则将通过显示错误信息的方式就有关情况向您进行告知。基于Windows NT操作系统的命令解释程序是Cmd.exe。而Windows 9x操作系统中的命令解释程序则是Command.exe。
此时此刻,上述脚本中的objShell.Run “ipconfig”命令将在其运行ipconfig程序的同时绕过命令解释程序;换句话说,该命令将在无须先运行命令解释程序再由命令解释程序运行ipconfig的前提下直接运行ipconfig。在某些情况下,这种方式或许利大于弊,但在这个示例中,我们却不希望绕过命令解释程序。为什么?因为命令解释程序可帮助我们发现“窗体一闪而过”问题的答案。正如您所看到的,命令解释程序可接受大量开关选项(如果您有兴趣了解cmd.exe或command.exe所具备的全部功能,则请在计算机帮助系统中查找该程序的可执行文件),而这些选项中的/k开关则恰恰用来指示命令解释程序在某一程序运行完毕后保持输出窗口的开启状态。我们需要借助这个选项来确保程序窗体不会在打开后立即关闭。
为实现上述目的,我们应将正在运行的命令从ipconfig修改为cmd.exe /k ipconfig或command.exe /k ipconfig,这里,cmd.exe对应于Windows NT操作系统,而command.exe则适用于Windows 9x操作系统。但是,如果您必须同时面向Windows NT和Windows 9x操作系统提供支持,又将如之奈何?针对我们正在使用的操作系统进行跟踪的确是一件颇为麻烦的事。也正是出于这种原因,我们才引用了一个名为%COMSPEC%的环境变量,以期提供通往适当命令解释程序的完整路径。该环境变量可确保下列脚本代码既可在Windows NT操作系统上运行,又能在Windows 9x操作系统上执行:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /k ipconfig"
请尝试运行这个经过修改的脚本。您只需启动记事本(或其它习惯使用的文件编辑器),并将%COMSPEC% /k添加到先前编写的脚本中,然后,将修改过的文件另存为RunIPConfig.vbs。接下来,在命令行窗体中导航至C:\Scripts目录,再通过输入cscript RunIPConfig.vbs命令并按回车键的方法运行该脚本。您这次将看到一个用来显示ipconfig命令输出结果的新窗体,具体情形如下图所示。
如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。
您接下来应该做的就是进行适用性测验。上述脚本所能运行的程序绝不仅限于ipconfig。而您所需要完成的全部工作仅仅是修改第二行代码中跟在Run方法后面的字符串。您可尝试将%COMSPEC% /k ipconfig分别替换为%COMSPEC% /k netstat或%COMSPEC% /k mmc。举例来说,您将可从某一脚本中运行GUI(图形用户界面)工具,而这个脚本则以运行计算器程序为例:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "Calc.exe"
您不仅能从某一脚本内部运行其它脚本,而且,还可从当前脚本中调用其它批处理文件;如果您碰巧拥有一些批处理文件,不妨尝试运行它们。当然,如果这些批处理文件的存储位置与您计算机上PATH环境变量的设定范围并不相符,您就应将相关存储位置添加到全局访问路径或单独指定通往批处理脚本的完整访问路径。举例来说,如果您在C:\Batchscripts目录下拥有一个名为Checkserver.bat的批处理脚本,那么,应由您传递给Run方法的字符串就应类似于:%COMSPEC% /k C:\batchscripts\checkserver.bat。
如果您已完成了上述试验,我们就将继续讲解后面的内容。您将学习到借助Run方法运行单一程序的具体方法。如果您需要连续运行两个程序,应如何是好?这恰恰是由下列脚本即将执行的任务:该脚本将在运行ping程序后,紧接着运行nslookup程序。请注意,您可将对应于所需运行程序的命令行参数包含在传递给Run方法的字符串当中。在此,我们将把127.0.0.1作为参数分别传递给Ping和Nslookup。
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /k ping 127.0.0.1"
objShell.Run "%COMSPEC% /k nslookup 127.0.0.1"
请按针对先前所述脚本的处理方法保存并运行这个脚本。脚本运行结果应该是两个命令行窗体同时打开,其中,Nslookup程序在一个窗体中运行,而Ping程序则在另一个窗体中以同步方式运行,具体情形正如以下屏幕快照所示。
如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。
在这个例子中,事实表明,实现Ping和Nslookup的同时运行根本不成问题。然而,如果您需要运行两个批处理脚本,并希望在第一个脚本运行完毕后再开始运行第二个脚本,又该如何是好?举例来说,第一个程序将针对某一特定类型的信息执行检索,并将其保存为一个文本文件;而第二个程序则将在前者基础上通读刚刚生成的文本文件,并针对相关内容执行特定操作。在这种情况下,两个程序的同时运行将是无法接受时;只有在第一个程序执行完毕的前提下,第二个程序才能开始运行。
到目前为止,我们一直都在传递给Run方法一个用来指定所需运行程序的字符串。Run方法将可再接收两个参数,而这两个参数中的每一个均为可选参数。第二个参数将允许您针对某一程序在开始运行时所呈现的窗体外观加以指定。并非所有程序都将使用到该参数,但对于那些使用该参数的程序来说,该参数却可帮助您启动一个呈现多种窗体风格(包括最小化、最大化和隐藏在内)的程序。我们并不打算在这篇专栏文章中过多涉及该参数。如果您需要了解有关该参数的更多信息资料,敬请查阅WSH在线文档http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28001169(点击接近本页面顶部的“Windows Script Host文档”链接)。
专供Run方法接收的第三个参数将允许我们防止相关程序以并发方式运行。您可将第三个参数赋值为True,以便指示脚本停留在使用Run方法的代码行并保持等待状态,直到已被激活的程序运行完毕。我们已经知道了因未设定该参数所产生的后果,该参数在缺省状态下被设定为False,而这种设置必将导致两个程序同时运行。
让我们将前面的脚本修改为先运行Ping程序,待Ping程序运行完毕后,再运行Nslookup程序的状态。
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /k ping 127.0.0.1",,True
objShell.Run "%COMSPEC% /k nslookup 127.0.0.1"
请注意,我们已将被赋值为True的第三个参数添加到应在脚本第二行中被调用的Run方法之后。我们之所以连续使用两个逗号的原因在于,如果我们只使用一个逗号,那么,Run方法便会认为我们随后指定的是第二个参数,而非第三个参数。如您所见,两个连续逗号之间并不存在任何内容,因此,也就不会有任何设置被当作第二个参数传递给Run方法。如果我们没有对某一参数专门赋值,那么,Run方法便会使用缺省值。举例来说,第三个参数的缺省值应该是False。
现在就让我们试着运行经过修改的脚本。您会马上注意到,只有Ping程序得到运行。当Ping运行完毕后,该程序运行时所使用的窗体仍在屏幕上保持开启状态;而Nslookup程序则尚未开始运行。请试着关闭这个窗体并查看接下来发生的情况。当您关闭Ping程序所使用的窗体后,Nslookup便会开始运行。请记住,您正在使用/k选项运行cmd.exe(或command.exe),也就是说,您已经告诉Run方法,直到cmd.exe运行完毕,方可继续执行后续指令。好的,由于我们事先设定了/k选项,因此,只有曾被要求保持开启状态的窗体得到关闭,cmd.exe才会执行完毕。
如果您需要运行两个批处理文件,并且无需查看它们的输出结果,那么,便可将/k选项删除,而这两个批处理文件仍将接续(而非同时)运行,这也恰恰是您在第二个程序信赖第一个程序运行结果的前提下所需确保的运行方式。
两个程序之间应就以下信息进行沟通,那就是,第一个程序实现运行的情况必须被告知第二个程序。某些程序将返回一个错误代码(也就是一个数字),用来指示自身是否已得到成功运行。而Run方法便可将这种错误代码返回给您所编写的脚本。正处于运行状态的程序必须在得知即将被返回的错误代码之前运行完毕,为此,您必须通过将Run方法的第三个参数设定为True的方式强制脚本等候程序运行完毕。
我们将在接下来的脚本中运行Ping程序,并通过针对Wscript对象使用Echo命令的方式将该程序所返回的错误代码显示出来。Wscript对象将不必被生成为类似于WshShell对象的状况,而您则可在脚本当中的任意控制点对它所提供的方法加以运用。
Set objShell = CreateObject(“Wscript.Shell”)
iErrorCode = objShell.Run(“ping 127.0.0.1”,,True)
Wscript.Echo iErrorCode
除具备错误代码检索功能外,以上脚本还在两方面与先前脚本有所区别。首先,请注意,即将被传递给Run方法的字符串已被加上了一对圆括号。这主要是因为,Run目前被要求返回一个数值。这属于VBScript语言的一项要求;如果您并未在此使用圆括号,便会在脚本运行过程中收到一条错误信息。应该被返回的数值是Ping程序的错误代码,并将被保存至变量iErrorCode,然后,借助WScript.Echo命令被显示出来。
需要给予关注的第二件事就是,我们并没有运行命令解释程序。我们希望错误代码来自Ping,而非来自Cmd.exe(或Command.exe),为此,我们直接运行了Ping程序。而由Ping返回的错误代码既不是很有趣,也不是很有用。当然,某些命令行工具却可返回可供您所编写的脚本做出相关判断(或生成日志)的有用错误代码。
从借助Run实现运行的某一程序中所获得的相关信息仅能满足最低使用需求,并很有可能不具备多少使用价值。举例来说,许多程序都将只返回一个0数值,以此表明自身已实现运行并且运行完毕。当然,它们并没有必要就自身成功运行且运行完毕的情况向您进行汇报。
当然,如果您已拥有WSH 5.6版(可从http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28001169页面下载),便具备了另一种可供使用的方法,以便运行那些可帮助您与当前所运行程序改善信息交流方式的程序。而这种方法便是Exec。它还是从属于WshShell对象的一种方法,这里所说的WshShell正是为使用Run而必须生成的那个对象。这对我们来说主要意味着,不必为开始利用Exec方法而针对脚本的第一行代码进行修改。
让我们直接编写一个利用Exec方法运行ipconfig程序的脚本。
Set objShell = CreateObject("WScript.Shell")
objShell.Exec "%COMSPEC% /k ipconfig"
上述脚本同我们为您展示的第二个脚本之间所存在的唯一区别就是,我们已在这个脚本中将objShell.Run修改为objShell.Exec。然而,当您运行这一个脚本时,将难以觉察到上述修改所产生的效果。您甚至无法看到那个一闪即逝的窗体。实际上,您根本看不到任何东西。如果我们此时告诉您,ipconfig实际上已运行完毕,不知您是否愿意相信?好吧,还是不要轻易相信我们所说的话;取而代之的做法是,在ipconfig命令后方添加一个重定向符号(>),并在针对ipconfig发出的调用后紧跟一个文本文件名。上述代码将导致命令执行结果被输出到指定文件。如果您尚未习惯使用重定向操作,不妨这样设想:如果我们将真实情况告诉您,而ipconfig程序的确处于运行状态,那么,它便会生成自己的标准文本显示信息。遗憾的是,我们将无法看到相关信息。重定向操作将允许我们捕捉到任何命令的输出结果,并将它们强行导向一个指定文件。这将有助于我们针对ipconfig命令是否处于运行状态加以确认。接下来的脚本可供用来将所需查看的输出结果呈现给我们。
Set objShell = CreateObject(“Wscript.Shell”)
objShell.Exec “%COMSPEC% /k ipconfig > ipconfig_output.txt”
在上述脚本运行完毕后,请查看ipconfig_output.txt文件内容。如需查看这个文本文件的内容,则请按下列屏幕快照所示键入type命令。
如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。
这就是您所得到的信息!我们的脚本就是实实在在地运行ipconfig,只不过没有让我们看到命令输出结果。无论您相信与否,这都算得上一件好事。Exec之所以没有为我们显示输出结果,恰恰是因为我们原本并未提出相关要求。正如您所看到的那样,我们可借助Exec针对输出结果的呈现和操作方式加以控制。
您是否还记得令Run方法返回错误代码的具体实现方式?Exec事实上可返回一个被称作WshScriptExec的完整对象。正如WshShell对象为我们提供针对Run和Exec这两种方法的访问调用权限那样,WshScriptExec对象将为我们提供针对附加功能特性的访问调用权限,而这些附加功能特性则允许我们围绕某一程序的输出结果展开操作。脚本中大量操作的实现都会以额外复杂性为代价,而上述附加功能特性也不例外。我们即将或多或少地遭遇这种复杂性,为此,请继续阅读本文,并在接下来的章节中确保集中精力。
Exec方法可供用来返回一个WshScriptExec对象。而在某一脚本中促成这一事件的发生则需要使用VBScript语言中的Set关键字,具体代码如下所示:
Set objWshShellExec = objShell.Exec(“ipconfig”)
说明:我们并未在此继续使用%COMSPEC%环境变量;该变量已不具备继续存在的必要,其原因主要体现为,我们不需要为确保某一并不存在的窗体处于开启状态而将/k选项传递给相关命令。那么,我们又该如何将这个窗体关闭并继续运行脚本代码呢?我们将可在此使用/c选项(该选项表示只运行一条命令,然后,接着执行后续代码);事实上,如果我们需要运行一条已被内建于命令解释程序的命令(例如dir),便会需要使用该选项。而像dir这样的工具本身并不属于工具范畴;它们更加近似于cmd.exe(或command.exe)命令的参数;正因如此,您才需要为确保它们发挥作用而指定%COMSPEC%这一环境变量。
当您将与WshShellExec对象相关的引用存储于objWshShellExec变量后,便已具备了开始围绕程序输出结果展开操作的必要条件,但此时的条件尚不够充分。而这正是复杂性乘虚而入的大好时机。正如Exec方法返回WshShellExec对象那样,WshShellExec对象亦可返回另一对象;这个对象将通过调用StdOut属性的方式被返回,而这恰恰允许您针对程序输出结果执行相关操作。
如果不对照一个示例脚本,上述思路几乎不可能得到理解。为此,我们专门编写了一个最为简单的示例,旨在针对由嵌套于WSH脚本的某一程序所产生的输出结果加以运用。请将该脚本当作一种特殊类型的重定向操作。只有在这种情况下,程序输出结果才不会被导入某一文件,取而代之的是,相关输出结果将被赋予一个名为strOutput的变量。遗憾的是,我们这回将不能仅仅使用一个简单的重定向符号(>),而必须围绕两个不同对象执行操作。
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig")
Set objStdOut = objWshScriptExec.StdOut
strOutput = objStdOut.ReadAll
WScript.Echo strOutput
由上述脚本生成的输出结果将被显示在专供脚本运行的窗体内;这里并没有新的窗体生成。事实上,如果您从命令行方式中运行ipconfig本身的话,输出结果看上去也将别无二帜。既然如此,为何不干脆采取这种方式?我们已经在脚本当中为输出结果生成了一个中间存储位置--strOutput变量。尽管我们将在上述脚本的下一行内利用Wscript.Echo命令针对输出结果加以显示,然而,却往往需要在执行显示操作前先对输出结果实施操控,只有这样,才能对由ipconfig工具显示的信息进行修改。
在尝试运行上述脚本之前,让我们先对它的最后三行代码给予更多关注;当然,您已经对前两行代码非常熟悉了。在第三行代码中,WshScriptExec对象所配备的StdOut属性将被用来检索代表正处于运行状态之程序(标准)输出结果的相关对象;而ipconfig则是本例中待处理结果的输出程序。在第四行代码中,ReadAll方法将被用来针对全部输出结果执行检索,并将其保存于strOutput变量。最后,也就是在第五行代码中,WScript.Echo将被用来显示输出结果。
我们现在已拥有了经常被当作ipconfig工具(或可供我们用来在上述脚本中替代ipconfig的其它任何工具)封装程序的对象。封装程序是一种可就另一程序功能特性加以应用、并能够以简便快捷方式针对已被封装程序功能进行修改的特殊程序。封装程序为我们创造了针对已被封装程序的输出结果进行修改的理想时机。而这恰恰是我们将利用本文剩余篇幅加以介绍的内容。
在围绕ipconfig工具开展自定义的过程中,我们将需要了解以每次一行的频率对程序输出结果进行相关处理的具体方法。当前,我们主要借助objStdOut.ReadAll对ipconfig工具的全部输出结果执行检索操作,并将检索结果保存于strOutput变量。而我们将在下一个脚本中执行的任务则是利用ReadLine(而非ReadAll)针对输出结果进行逐行检索。我们将对输出结果的每一行进行检查,如果任意一行包括“Physical Address”(物理地址)字符串,就会将它显示出来;否则,便不会显示这行输出结果。我们只对包含“Physical Address”(物理地址,也就是对应于网卡的MAC地址)字符串的输出结果行执行了筛选操作,并未将其它任何内容显示出来。
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig /all")
Set objStdOut = objWshScriptExec.StdOut
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
If InStr(strLine,"Physical Address") Then
WScript.Echo strLine
End If
Wend
上述脚本的前三行看上去多少有些眼熟;请注意,我们必须将/all选项添加至ipconfig命令后方,以确保Physical Address(物理地址)被显示出来。这个脚本同上个脚本之间的主要区别在于,前者使用了While/Wend循环语句。我们将使用ReadLine方法对单个输出结果行执行检索操作,但却需要掌握针对是否超出行检索范围的状态加以判定的具体手段。而这恰恰是While/Wend循环和objStdOut.AtEndOfStream指令的用武之地。只要程序尚未触及(标准)输出结果数据流的结尾,上述循环便会保持接续执行状态(而符合检索条件的输出结果行则将被保存至strLine变量)。您可将一个数据流想象为由一系列字符排列而成的长串,而您则可按排列顺序对其进行相关处理;本例中的数据流便是ipconfig /all命令的完整输出结果。
每当我们完成一次程序循环时,便会将下一行内容保存至strLine变量,并利用If/Then语句决定是否应对该行内容加以显示。我们主要借助InStr(字符串命令)功能对存储在strLine变量当中的输出结果行是否包含“Physical Address”(物理地址)加以判断。如果当前行确实包含有“Physical Address”(物理地址),就应使用WScript.Echo命令将它显示出来。以下屏幕快照展现了由脚本生成的部分典型输出结果。
如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。
我们的下一个脚本将使用与上一个脚本完全相同的基本组件,所不同的是,我们已不再针对输出结果执行筛选操作,而是向它们当中添加特定内容。鉴于ipconfig /all命令可针对DHCP释放获取时机及其超时状态信息执行检索,因此,将当前日期和时间包含于命令输出结果的处理方法或许具备一定实用价值。接下来的脚本正是用来实现这一设想。
脚本一开始便针对输出结果的前四行执行检索和显示操作,并且对每一行所采取的方法完全相同--先调用ReadLine命令,紧接着调用WScript.Echo命令。当输出结果的第四行已被检索并显示出来后,我们便生成了一个包含有当前日期和时间标注信息的字符串。而这里所说的当前日期和时间则是由VBScript所配备的Now()函数提供的。
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig /all")
Set objStdOut = objWshScriptExec.StdOut
'
' Skip first four lines
'
strLine = objStdOut.ReadLine
WScript.Echo strLine
strLine = objStdOut.ReadLine
WScript.Echo strLine
strLine = objStdOut.ReadLine
WScript.Echo strLine
strLine = objStdOut.ReadLine
WScript.Echo strLine
'
' Add date/time information
'
strCurrentTime = " Current Date/Time. . . . . . . . .: " & Now()
WScript.Echo strCurrentTime
'
' Display the rest of the output
'
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
WScript.Echo strLine
Wend
毋庸置疑,上述脚本已开始变得多少有些复杂了。而解读这一脚本的最佳方法则是逐段分析。您应对该脚本的前三行较为熟悉。而下一个附有注释的部分则主要借助ReadLine和Echo命令对ipconfig /all输出结果的前四行执行读取和显示操作。
附有注释的下一部分自然以编排将被临时存储于strCurrentTime变量的新信息行为起点。这个信息行将由一个与VBScript Now()函数调用操作相关联的简单字符串构成,而VBScript Now()函数则用来提供当前日期和时间信息。一旦这个信息行编排完毕并被保存于strCurrentTime变量,我们便可当即使用WScript.Echo命令对其加以显示。
在最后一个附有注释的部分中,我们将对输出结果的剩余内容执行循环操作,并在无需进行任何修改的前提下对其进行逐行显示。以下屏幕快照展现了脚本运行产生的典型输出结果。请注意,脚本输出结果看上去与ipconfig的标准输出结果别无二帜。而由我们插入Host Name(主机名称)行下方的Current Date/Time(当前日期/时间)行则与全新的上下文环境结合得天衣无缝。
如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。
最后,让我们使用For/Next循环语句执行前四行内容的输出操作,以便使脚本变得更加精简,具体代码如下所示。
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig /all")
Set objStdOut = objWshScriptExec.StdOut
'
' Skip first four lines
'
For i = 1 To 4
strLine = objStdOut.ReadLine
WScript.Echo strLine
Next
'
' Add date/time information
'
strCurrentTime = " Current Date/Time. . . . . . . . .: " & Now()
WScript.Echo strCurrentTime
'
' Display the rest of the output
'
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
WScript.Echo strLine
Wend
事实上,还存在着从WSH脚本中运行其它程序的另一种替代方法:即针对Windows管理规范(WMI)加以应用。您将可借助WMI完成一系列Windows管理任务!虽然借助WMI实现程序运行的方式将涉及相对复杂的语法,但却可帮助您完成Run和Exec无法实现的任务,例如,设定程序运行优先级或基于远程计算机运行相关程序。在此,我们诚恳地建议您尽可能了解有关WMI的更多信息资料。如果您确实对此抱有兴趣(我们希望您能够这样),则请到MSDN网站上一个名为Scripting Clinic(脚本诊所)的专栏中查阅由三部分组成的系列文章(http://msdn.microsoft.com/columns)。
好在我们已回答了您针对从WSH脚本中运行其它程序而产生的某些疑难问题。我们还为您提供了有关Run和Exec方法的简要概述,并初步涉及了存在于两者之间的某些差异--其中,最明显的区别体现为,Exec方法将允许您针对程序输出结果进行处理,而Run方法则不具备这种能力。另一个重要区别是:只有WSH 5.6及其后续版本方可提供Exec方法。
我们衷心希望您能够对第一篇专栏文章感到满意。请将您的意见和观点发送至:scripter@microsoft,以便让我们有所了解。此外,请务必告诉我们您希望以后各期专栏能够涉及哪些内容。如果您能够在百忙之中抽出宝贵时间,则请查阅刊载于Scripting Clinic(脚本诊所)专栏的WMI系列文章;如果您利用在这里学到的知识技能完成了某些既简洁明快又富于实用价值的工作,就请将事情的经过记录下来;我们非常乐于听到与这方面有关的消息!
Re electronixtar:
For this topic, the following linked article explains it in detail.
Quoted from: Microsoft TechNet: Script Talk -- October 2002: Running Programs from WSH Scripts
http://www.microsoft.com/china/technet/archives/columns/scripts/sg1002.asp
Script Talk -- October 2002
Running Programs from WSH Scripts
Scripting Expert Group
The Scripting Expert Group sincerely welcomes you to visit this newly opened monthly column. We originally hoped to create this column on our own, but we really couldn't manage it. As you can see, this is not really our column; it belongs to you. You send a large number of carefully prepared emails to scripter@microsoft.com, and this column is precisely (and will continue to be) based on the questions and comments you provide. For this reason, the Scripting Expert Group can welcome everyone to visit their own column in an orderly manner; we sincerely hope you can find information here that is both pleasing to the eye and of practical value. If the content presented in this column does not satisfy you, please feel free to give us your advice!
One of the more common questions we receive is how to run a program from a WSH script. The following is a representative excerpt from such an email.
You mentioned in the webcast two lines of script code that help you run an external program. Can you provide an example sample of the code?
In response to the above question, we have decided to take up the first issue of this column to introduce you to how to run external programs from your own scripts. Why do you need to run an external program from a script? Just imagine: command-line tools allow you to perform a set of specific tasks, and batch scripts provide the necessary logical threads for you to stitch these tasks together to build the basic elements of a custom solution. But what if the logical threads provided by the batch script are not powerful enough, or the necessary components to build the solution are not provided by the command-line tool? This is where WSH scripts come into play. Such scripts allow you to apply the powerful logical threads provided by scripting languages such as VBScript, and use powerful tools such as WMI and ADSI as well as command-line tools and batch scripts to implement your own task solutions.
Let's immediately start writing an example script. In fact, we should first make sure there is a physical location to save this script before writing the script. If there is no folder named C:\Scripts on the computer you are using, please go back to the root directory and create this folder. When you have completed the above work, you should open Notepad or other text editor, type the following script code, and save it to your C:\Scripts folder with the file name RunIPConfig.vbs.
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "ipconfig"
Before trying to run the script you just generated, let's check it and try to predict the possible running result in advance. There are two hints in this script that help us predict the running result. The first line of code includes the verb Create (actually CreateObject), and the second line of code contains the verb Run (run). It can be seen that this script may first generate something called an object and then run a specific program. In fact, it looks more like the script will run a command-line tool named ipconfig.exe.
The above prediction does match the running result of the script. The script first generates something called an object. In this example, the object generated by the script is the Shell (WshShell) object. You can think of an object as something similar to a command-line tool; and your script can use it to perform a specific type of task. The Shell object allows you to perform tasks that could originally be performed in the Windows command interpreter from the script--like running a program.
Unlike a command-line tool, you must first generate a new object before starting to apply it. When generating the object, you should also assign it a name that will be used to reference it in the rest of the script. In this example, the name we use is objShell. When the object is generated and given a relevant name, we can use the object to perform relevant tasks by adding a dot (.) after the object name and then the name of the task to be completed. The task name in this example is Run. And Run is a well-known Shell object method.
Now, open a command-line window and navigate to the C:\Scripts folder. To run the script you just wrote, please enter the cscript RunIPConfig.vbs command and press Enter. You will see a window flash on the screen, but the content displayed in the window disappears before you can see it! You can try running the script repeatedly and try to decipher the information that disappears in the window. This may be an interesting thing, but it can be done in a simpler way.
To make it easier for you to understand, we must pay attention to the events that occur while you are running the command-line tool. When you enter ipconfig at the command line and press Enter, you issue an instruction to the command interpreter. The command interpreter will check the instruction you entered. If the command you entered represents a valid program, the command interpreter will run the program for you. If the command you entered does not represent a valid program, the command interpreter will inform you of the relevant situation by displaying an error message. The command interpreter based on the Windows NT operating system is Cmd.exe. And the command interpreter in the Windows 9x operating system is Command.exe.
At this moment, the objShell.Run "ipconfig" command in the above script will run the ipconfig program while bypassing the command interpreter; in other words, the command will run ipconfig directly without first running the command interpreter and then having the command interpreter run ipconfig. In some cases, this method may have more advantages than disadvantages, but in this example, we do not want to bypass the command interpreter. Why? Because the command interpreter can help us find the answer to the "window flashes by" problem. As you can see, the command interpreter can accept a large number of switch options (if you are interested in all the functions of cmd.exe or command.exe, please look up the executable file of this program in the computer help system), and the /k switch in these options is exactly used to instruct the command interpreter to keep the output window open after a program runs. We need to use this option to ensure that the program window does not close immediately after opening.
To achieve the above purpose, we should modify the command being run from ipconfig to cmd.exe /k ipconfig or command.exe /k ipconfig, where cmd.exe corresponds to the Windows NT operating system and command.exe is suitable for the Windows 9x operating system. But what if you have to support both Windows NT and Windows 9x operating systems? It is quite troublesome to track the operating system we are using. It is for this reason that we quoted an environment variable named %COMSPEC% to provide the complete path to the appropriate command interpreter. This environment variable ensures that the following script code can run on both the Windows NT operating system and the Windows 9x operating system:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /k ipconfig"
Please try to run this modified script. You just need to start Notepad (or other file editor you are used to), add %COMSPEC% /k to the previously written script, and then save the modified file as RunIPConfig.vbs. Next, navigate to the C:\Scripts directory in the command-line window, and then run the script by entering the cscript RunIPConfig.vbs command and pressing Enter. This time you will see a new window displaying the output of the ipconfig command, as shown in the following figure.
If your browser does not support the embedded frame, please, click here to browse in a separate page.
What you should do next is to test for applicability. The program that the above script can run is not limited to ipconfig. All you need to do is modify the string after the Run method in the second line. You can try replacing %COMSPEC% /k ipconfig with %COMSPEC% /k netstat or %COMSPEC% /k mmc respectively. For example, you can run a GUI (graphical user interface) tool from a script, and this script takes running the calculator program as an example:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "Calc.exe"
You can not only run other scripts from within a script, but also call other batch files from the current script; if you happen to have some batch files, you can try running them. Of course, if the storage location of these batch files does not match the setting range of the PATH environment variable on your computer, you should add the relevant storage location to the global access path or specify the complete access path to the batch script separately. For example, if you have a batch script named Checkserver.bat in the C:\Batchscripts directory, then the string you pass to the Run method should be similar to: %COMSPEC% /k C:\batchscripts\checkserver.bat.
If you have completed the above experiment, we will continue to explain the following content. You will learn how to use the Run method to run a single program. What should you do if you need to run two programs consecutively? This is exactly the task that the following script will perform: the script will run the ping program and then the nslookup program immediately. Please note that you can include the command-line parameters corresponding to the program you need to run in the string passed to the Run method. Here, we will pass 127.0.0.1 as parameters to Ping and Nslookup respectively.
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /k ping 127.0.0.1"
objShell.Run "%COMSPEC% /k nslookup 127.0.0.1"
Please save and run this script according to the processing method for the previously described script. The running result of the script should be that two command-line windows open at the same time, where the Nslookup program runs in one window and the Ping program runs synchronously in the other window, as shown in the following screenshot.
If your browser does not support the embedded frame, please, click here to browse in a separate page.
In this example, it turns out that it is not a problem at all to run Ping and Nslookup at the same time. However, what if you need to run two batch scripts and want the second script to start running only after the first script has finished running? For example, the first program will retrieve a certain type of information and save it as a text file; the second program will then read the just-generated text file and perform specific operations on the relevant content. In this case, running the two programs at the same time is not acceptable; the second program can only start running if the first program has finished executing.
So far, we have been passing a string to the Run method to specify the program we need to run. The Run method can accept two more parameters, each of which is optional. The second parameter will allow you to specify the appearance of the window when a program starts running. Not all programs will use this parameter, but for those that do, this parameter can help you start a program that presents a variety of window styles, including minimized, maximized, and hidden. We are not going to go into too much detail about this parameter in this column article. If you need to know more information about this parameter, please refer to the WSH online documentation http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28001169 (click the "Windows Script Host Documentation" link near the top of this page).
The third parameter specifically for the Run method will allow us to prevent related programs from running concurrently. You can assign the third parameter a value of True to instruct the script to stay on the line of code using the Run method and wait until the activated program has finished running. We already know the consequences of not setting this parameter. The parameter is set to False by default, and this setting will definitely cause two programs to run at the same time.
Let's modify the previous script to the state where the Ping program runs first and then the Nslookup program runs after the Ping program has finished running.
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /k ping 127.0.0.1",,True
objShell.Run "%COMSPEC% /k nslookup 127.0.0.1"
Please note that we have added the third parameter assigned as True to the Run method called in the second line of the script. The reason we use two commas in a row is that if we use only one comma, then the Run method will think that what we specify next is the second parameter, not the third parameter. As you can see, there is nothing between the two consecutive commas, so no setting will be passed to the Run method as the second parameter. If we do not assign a specific value to a parameter, the Run method will use the default value. For example, the default value of the third parameter should be False.
Now let's try to run the modified script. You will immediately notice that only the Ping program is run. When Ping finishes running, the window used by the program remains open on the screen; the Nslookup program has not started running yet. Try to close this window and see what happens next. When you close the window used by the Ping program, Nslookup will start running. Please remember that you are running cmd.exe (or command.exe) with the /k option, which means you have told the Run method to continue executing subsequent instructions only when cmd.exe has finished running. Well, since we set the /k option in advance, cmd.exe will only finish executing when the window that was required to stay open is closed.
If you need to run two batch files and do not need to view their output, you can delete the /k option, and the two batch files will still run consecutively (instead of simultaneously), which is exactly the running method you need to ensure when the second program depends on the running result of the first program.
There should be communication between the two programs, that is, the fact that the first program has been run must be informed to the second program. Some programs will return an error code (that is, a number) to indicate whether they have been successfully run. And the Run method can return this error code to the script you wrote. The program that is running must finish running before the error code to be returned is known, so you must force the script to wait for the program to finish running by setting the third parameter of the Run method to True.
We will run the Ping program in the next script and display the error code returned by this program by using the Echo command for the Wscript object. The Wscript object does not need to be generated in the same way as the WshShell object, and you can use the methods it provides at any control point in the script.
Set objShell = CreateObject("Wscript.Shell")
iErrorCode = objShell.Run("ping 127.0.0.1",,True)
Wscript.Echo iErrorCode
In addition to having the error code retrieval function, the above script is different from the previous script in two aspects. First, please note that the string to be passed to the Run method has been enclosed in a pair of parentheses. This is mainly because Run is currently required to return a value. This is a requirement of the VBScript language; if you do not use parentheses here, you will receive an error message during script execution. The value that should be returned is the error code of the Ping program, and it will be saved in the variable iErrorCode, and then displayed with the WScript.Echo command.
The second thing to pay attention to is that we are not running the command interpreter. We want the error code to come from Ping, not from Cmd.exe (or Command.exe), so we directly run the Ping program. The error code returned by Ping is neither very interesting nor very useful. Of course, some command-line tools can return useful error codes that can be used by the script you write to make judgments (or generate logs).
The relevant information obtained from a program run by Run has only the minimum usage requirements and is likely not very useful. For example, many programs will only return a 0 value to indicate that they have been run and have finished running. Of course, they don't have to report to you that they have run and finished successfully.
Of course, if you have WSH version 5.6 (available for download from the http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28001169 page), you have another method available to run programs that can help you improve the information exchange method with the currently running program. And this method is Exec. It is also a method belonging to the WshShell object, and the WshShell is the object that must be generated to use Run. This mainly means for us that we don't need to modify the first line of code of the script to start using the Exec method.
Let's directly write a script that uses the Exec method to run the ipconfig program.
Set objShell = CreateObject("WScript.Shell")
objShell.Exec "%COMSPEC% /k ipconfig"
The only difference between the above script and the second script we showed you is that we have changed objShell.Run to objShell.Exec in this script. However, when you run this script, you will hardly notice the effect of this modification. You can't even see the window that flashes by. In fact, you can't see anything. If we tell you now that ipconfig has actually finished running, would you be willing to believe it? Well, don't believe us easily; instead, add a redirection symbol (>) after the ipconfig command and follow a text file name after the call to ipconfig. The above code will cause the command execution result to be output to the specified file. If you are not used to using redirection operations, you can think of it this way: if we tell you the truth, and the ipconfig program is indeed running, then it will generate its own standard text display information. Unfortunately, we won't be able to see the relevant information. Redirection operations will allow us to capture the output of any command and force them to be directed to a specified file. This will help us confirm whether the ipconfig command is running. The following script can be used to present the output results we need to view to us.
Set objShell = CreateObject("Wscript.Shell")
objShell.Exec "%COMSPEC% /k ipconfig > ipconfig_output.txt"
After the above script runs, please check the content of the ipconfig_output.txt file. To view the content of this text file, please type the type command as shown in the following screenshot.
If your browser does not support the embedded frame, please, click here to browse in a separate page.
This is the information you get! Our script is actually running ipconfig, but we didn't see the command output result. Whether you believe it or not, this is a good thing. The reason why Exec does not display the output result for us is precisely because we did not originally make such a request. As you can see, we can use Exec to control the presentation and operation methods of the output result.
Do you still remember how to make the Run method return an error code? Exec can actually return a complete object called WshScriptExec. Just as the WshShell object provides us with access to the Run and Exec methods, the WshScriptExec object provides us with access to additional functional features, and these additional functional features allow us to operate around the output result of a program. The implementation of a large number of operations in the script will come at the cost of additional complexity, and the above additional functional features are no exception. We are going to encounter this complexity more or less, so please continue reading this article and make sure to concentrate in the next section.
The Exec method can be used to return a WshScriptExec object. And to make this happen in a script, the Set keyword in the VBScript language needs to be used, as shown in the following code:
Set objWshShellExec = objShell.Exec("ipconfig")
Explanation: We are not continuing to use the %COMSPEC% environment variable here; this variable is no longer necessary, mainly because we don't need to pass the /k option to the relevant command to ensure that a non-existent window is kept open. Then, how can we close this window and continue running the script code? We can use the /c option here (this option means to run only one command and then continue executing the subsequent code); in fact, if we need to run a command built into the command interpreter (such as dir), we will need to use this option. Tools like dir themselves are not in the tool category; they are more like parameters of the cmd.exe (or command.exe) command; for this reason, you need to specify the %COMSPEC% environment variable to ensure that they work.
When you store the reference related to the WshShellExec object in the objWshShellExec variable, you have the necessary conditions to start operating around the program output result, but the conditions are not yet sufficient. This is where complexity steps in. Just as the Exec method returns the WshScriptExec object, the WshScriptExec object can also return another object; this object will be returned by calling the StdOut property, and this just allows you to perform related operations on the program output result.
This idea is almost impossible to understand without referring to an example script. Therefore, we have specially written the simplest example to apply the output result generated by a program nested in a WSH script. Please treat this script as a special type of redirection operation. In this case, the program output result will not be imported into a file; instead, the relevant output result will be assigned to a variable named strOutput. Unfortunately, this time we can't just use a simple redirection symbol (>), but we must operate around two different objects.
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig")
Set objStdOut = objWshScriptExec.StdOut
strOutput = objStdOut.ReadAll
WScript.Echo strOutput
The output result generated by the above script will be displayed in the window dedicated to running the script; no new window is generated. In fact, if you run ipconfig itself from the command line, the output result will look the same. If that's the case, why not just take this approach? We have generated an intermediate storage location for the output result in the script--the strOutput variable. Although we will use the Wscript.Echo command to display the output result in the next line of the above script, we often need to manipulate the output result before performing the display operation, so that we can modify the information displayed by the ipconfig tool.
Before trying to run the above script, let's pay more attention to its last three lines of code; of course, you are already very familiar with the first two lines of code. In the third line of code, the StdOut property equipped with the WshScriptExec object will be used to retrieve the relevant object representing the (standard) output result of the program that is running; and ipconfig is the output program of the result to be processed in this example. In the fourth line of code, the ReadAll method will be used to retrieve all the output results and save them in the strOutput variable. Finally, in the fifth line of code, WScript.Echo will be used to display the output result.
We now have an object that is often used as a wrapper program for the ipconfig tool (or any other tool we can use to replace ipconfig in the above script). A wrapper program is a special program that can apply the functional characteristics of another program and can modify the function of the encapsulated program in a simple and fast way. The wrapper program creates an ideal opportunity for us to modify the output result of the encapsulated program. And this is exactly what we will introduce in the remaining part of this article.
In customizing around the ipconfig tool, we will need to understand how to process the program output result line by line. Currently, we mainly use objStdOut.ReadAll to retrieve all the output results of the ipconfig tool and save the retrieved results in the strOutput variable. The task we will perform in the next script is to use ReadLine (instead of ReadAll) to retrieve the output result line by line. We will check each line of the output result, and if any line includes the string "Physical Address" (physical address), we will display it; otherwise, we will not display this line of output result. We only filtered the output result line containing the string "Physical Address" (physical address, which is the MAC address corresponding to the network card), and did not display anything else.
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig /all")
Set objStdOut = objWshScriptExec.StdOut
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
If InStr(strLine, "Physical Address") Then
WScript.Echo strLine
End If
Wend
The first three lines of the above script look a bit familiar; please note that we must add the /all option to the ipconfig command to ensure that Physical Address (physical address) is displayed. The main difference between this script and the previous script is that the former uses the While/Wend loop statement. We will use the ReadLine method to retrieve a single output result line, but we need to master the specific means to determine whether we have exceeded the line retrieval range. This is where the While/Wend loop and the objStdOut.AtEndOfStream instruction come into play. As long as the program has not reached the end of the (standard) output result data stream, the above loop will continue to execute (and the output result line that meets the retrieval conditions will be saved in the strLine variable). You can think of a data stream as a long string composed of a series of characters, and you can process it in the order of arrangement; the data stream in this example is the complete output result of the ipconfig /all command.
Whenever we complete a program loop, we will save the next line of content in the strLine variable and use the If/Then statement to decide whether to display this line of content. We mainly use the InStr (string command) function to determine whether the output result line stored in the strLine variable contains "Physical Address" (physical address). If the current line does contain "Physical Address" (physical address), it should be displayed using the WScript.Echo command. The following screenshot shows part of the typical output result generated by the script.
If your browser does not support the embedded frame, please, click here to browse in a separate page.
Our next script will use the same basic components as the previous script, except that we no longer filter the output result, but add specific content to them. Since the ipconfig /all command can retrieve information about DHCP release acquisition time and its timeout status, it may be useful to include the current date and time in the processing of the command output result. The following script is exactly to realize this idea.
The script starts by retrieving and displaying the first four lines of the output result, and the method used for each line is exactly the same--first call the ReadLine command, and then call the WScript.Echo command. When the fourth line of the output result has been retrieved and displayed, we generate a string containing the current date and time annotation information. The current date and time here are provided by the Now() function equipped with VBScript.
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig /all")
Set objStdOut = objWshScriptExec.StdOut
'
' Skip first four lines
'
strLine = objStdOut.ReadLine
WScript.Echo strLine
strLine = objStdOut.ReadLine
WScript.Echo strLine
strLine = objStdOut.ReadLine
WScript.Echo strLine
strLine = objStdOut.ReadLine
WScript.Echo strLine
'
' Add date/time information
'
strCurrentTime = " Current Date/Time. . . . . . . . .: " & Now()
WScript.Echo strCurrentTime
'
' Display the rest of the output
'
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
WScript.Echo strLine
Wend
There is no doubt that the above script has started to become a bit more complicated. And the best way to interpret this script is to analyze it section by section. You should be familiar with the first three lines of the script. The next commented part mainly uses the ReadLine and Echo commands to read and display the first four lines of the ipconfig /all output result.
The next commented part naturally starts with arranging the new information line that will be temporarily stored in the strCurrentTime variable. This information line will be composed of a simple string associated with the VBScript Now() function call operation, and the VBScript Now() function is used to provide current date and time information. Once this information line is arranged and saved in the strCurrentTime variable, we can immediately use the WScript.Echo command to display it.
In the last commented part, we will loop through the remaining content of the output result and display it line by line without any modification. The following screenshot shows the typical output result generated by the script. Please note that the script output result looks the same as the standard output result of ipconfig. And the Current Date/Time (current date/time) line inserted by us below the Host Name (host name) line fits seamlessly with the new context.
If your browser does not support the embedded frame, please, click here to browse in a separate page.
Finally, let's use the For/Next loop statement to perform the output operation of the first four lines to make the script more concise, as shown in the following code.
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("ipconfig /all")
Set objStdOut = objWshScriptExec.StdOut
'
' Skip first four lines
'
For i = 1 To 4
strLine = objStdOut.ReadLine
WScript.Echo strLine
Next
'
' Add date/time information
'
strCurrentTime = " Current Date/Time. . . . . . . . .: " & Now()
WScript.Echo strCurrentTime
'
' Display the rest of the output
'
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
WScript.Echo strLine
Wend
In fact, there is another alternative method to run other programs from the WSH script: to apply Windows Management Instrumentation (WMI). You can use WMI to complete a series of Windows management tasks! Although the way to run a program using WMI will involve relatively complex syntax, it can help you complete tasks that Run and Exec cannot achieve, such as setting the program running priority or running related programs based on a remote computer. Here, we sincerely suggest that you try to learn more about WMI. If you are really interested in this (we hope you will be), please go to a column called Scripting Clinic (Script Clinic) on the MSDN website to check the three-part series of articles (http://msdn.microsoft.com/columns).
Fortunately, we have answered some of your questions about running other programs from the WSH script. We also provided a brief overview of the Run and Exec methods and initially touched on some of the differences between them--the most obvious difference is that the Exec method allows you to process the program output result, while the Run method does not have this ability. Another important difference is that the Exec method is only available in WSH 5.6 and later versions.
We sincerely hope you are satisfied with the first column article. Please send your opinions and views to: scripter@microsoft to let us know. In addition, be sure to tell us what content you want the columns in the future to cover. If you can spare some valuable time, please refer to the WMI series of articles published in the Scripting Clinic (Script Clinic) column; if you use the knowledge and skills learned here to complete some work that is both concise and practical, please record the process; we are very happy to hear about such news!
|

※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-6-9 03:23 |
|
|
electronixtar
铂金会员
      
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
呵呵,对!
最近研究XMLHttp,做网站自动登陆,必须输出一个 .js,里面有个函数,我就用 WshShell.Exec "cscript xxxx.js //NoLogo"来获得函数值的,呵呵~~很有用的方法~~
Hehe, right!
Recently researching XMLHttp, for website automatic login, I need to output a .js with a function. I use WshShell.Exec "cscript xxxx.js //NoLogo" to get the function value. Hehe~ A very useful method~
|

C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>" |
|
2006-6-9 10:55 |
|
|
vlq5299
初级用户
 
积分 136
发帖 59
注册 2006-6-2
状态 离线
|
|
2006-6-11 17:51 |
|
|
mobo
初级用户
 
积分 73
发帖 30
注册 2006-9-18
状态 离线
|
『第 7 楼』:
SYSTEMINFO在CMD下不便输出文本文件,用标准输出就行了!
使用 LLM 解释/回答一下
'''SYSTEMINFO在CMD下不便输出文本文件,用标准输出就行了!
'''自带参数的用法 ---------By MOBO[墨伯]:
Set objShell = CreateObject("WScript.Shell")
Set objExecObject = objShell.Exec("%comspec% /c SYSTEMINFO /FO LIST" )
'''读取运行后的标准输出:
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
Loop
'''用文本文件输出:
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.CreateTextFile("SYSTEMINFO.txt", true)
ts.Write strText
Set ts=nothing
Set fso=nothing
'''本来想用网页输出的,但不美!
'''SYSTEMINFO is not convenient to output text files under CMD, just use standard output!
'''Usage of self - contained parameters ---------By MOBO:
Set objShell = CreateObject("WScript.Shell")
Set objExecObject = objShell.Exec("%comspec% /c SYSTEMINFO /FO LIST" )
'''Read the standard output after running:
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
Loop
'''Output with text file:
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.CreateTextFile("SYSTEMINFO.txt", true)
ts.Write strText
Set ts=nothing
Set fso=nothing
'''Originally wanted to output with web page, but it is not beautiful!
|
|
2006-9-19 08:29 |
|
|
electronixtar
铂金会员
      
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『第 8 楼』:
使用 LLM 解释/回答一下
有vbs+WMI就不用systeminfo费事了
If there are VBS + WMI, there's no need to bother with systeminfo.
|

C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>" |
|
2006-9-19 08:58 |
|
|
lxmxn
版主
       
积分 11386
发帖 4938
注册 2006-7-23
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
我按照楼主说的做了,可以结果并没有显示出来。
就是一个msgbox消息框跳出来了,里面什么消息都没有,这是咋回事哦?
I did as the thread starter said, but the result didn't show up.
Just a msgbox popped up, with no messages in it. What's going on here?
|
|
2006-10-8 21:14 |
|
|
electronixtar
铂金会员
      
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『第 10 楼』:
使用 LLM 解释/回答一下
不会的吧,注意要有参数哦
Won't it be? Pay attention to having parameters
|

C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>" |
|
2006-10-8 21:46 |
|
|
lxmxn
版主
       
积分 11386
发帖 4938
注册 2006-7-23
状态 离线
|
『第 11 楼』:
使用 LLM 解释/回答一下
Originally posted by mobo at 2006-9-19 08:29:
'''SYSTEMINFO在CMD下不便输出文本文件,用标准输出就行了
可以输出到文本文件啊,为什么说不便?
Originally posted by mobo at 2006-9-19 08:29:
'''SYSTEMINFO in CMD is not convenient to output to a text file, just use standard output
You can output to a text file. Why do you say it's inconvenient?
|
|
2006-10-8 22:21 |
|
|
lxmxn
版主
       
积分 11386
发帖 4938
注册 2006-7-23
状态 离线
|
『第 12 楼』:
使用 LLM 解释/回答一下
再来试了一下,果然可以,看来当初是我搞错了,没有加参数。
另外,mobo的vbs脚本,和 systeminfo > systeminfo.txt 的效果是一样的。测试通过。
Tried again, and it果然 works. It seems I made a mistake earlier by not adding parameters.
Also, the effect of the mobo's vbs script is the same as systeminfo > systeminfo.txt. The test passed.
|
|
2006-12-28 12:11 |
|
|
jmz573515
银牌会员
    
积分 1212
发帖 464
注册 2006-12-13
状态 离线
|
|
2006-12-28 21:29 |
|
|
gne3
高级用户
    DOS学徒
积分 526
发帖 252
注册 2007-2-12
状态 离线
|
|
2007-2-18 04:43 |
|
|