脚本

脚本故事

发布者 The Scripting Guys

scrptguy

谈谈脚本的输出

您是否有过这样的经历,写了一个脚本,当您从命令行运行它时却只看到模糊的一行行数据快速向上翻滚,带走了您创建这个脚本所要获得的所有信息。怎样解决这个问题?你可能会把时间浪费在配置命令行窗口的属性上,加大它的缓冲区;在理论上,这可以使你往上滚动窗口,并查看信息。(为什么说是在“理论上”?因为有些信息可能还是无法显示在命令行窗口中。)

当然,通过上下卷动命令行窗口来了解数据是再简单不过了。但是假如您希望用一种更为永久的格式将其暂时存储到一个文档中该怎么办?听起来没有办法做到这一点是吗?那么,既然 没有希望,我们就下个月再见吧。

不,我们只是在开个玩笑;使用脚本,就 总有 希望。事实证明,有一些简单的方法可以创造更具有可读性,也更为持久的输出。例如,您可以使用命令外壳的重定向器 ( > 符号) 来向文本文档发送输出而不是将其显示在外壳窗口中。这样,您可以使用任何使用了 Wscript.Echo 语句的脚本来显示输出,也就是将输出保存为文本文档。而要做到这一切,只要写一行简单的代码就能完成。

尝试一下用以下 WMI 脚本输出的重定向技术,它能显示有关进程的信息。

Set objWMI = _
   GetObject("winmgmts:{impersonationLevel=impersonate}//./root/cimv2")
Set colProcesses = objWMI.ExecQuery("SELECT * FROM Win32_Process")
For Each objProcess In colProcesses
   WScript.Echo "进程名称: "    & objProcess.Name
   WScript.Echo "可执行文件的路径: " & objProcess.ExecutablePath
   WScript.Echo ".............................................."
   WScript.Echo vbCrLf
Next

将脚本输入文字编辑器,例如记事本,将其另存为一个以.vbs为扩展名的文档。当你保存这个脚本时,请确保这个记事本文档不要被添上了 .txt 的扩展名,不要将它命名为 MyScript.vbs.txt。也许更容易“注意”到这点的做法是当您向记事本文档名的文本框中录入的时候,就用双引号将您所选择的文档名引起来(例如,“DisplayProcesses.vbs”)。换句话说就是:

当您在命令提示符中输入 cscript DisplayProcesses.vbs 来运行脚本时,您可能无法看清命令行窗口中的信息,所有在电脑上运行程序所得到的结果都一闪而过(但是这取决于您的电脑上运行着多少程序)。

现在,再次运行脚本,这一次脚本的输出将被重定向到一个名为 output.txt 的文本文档。在命令提示符中输入 cscript DisplayProcesses.vbs > output.txt 。这次您就不会在命令行窗口中看到任何输出了。为什么呢?因为您已经命令脚本创造了一个新的文本文档,名为 output.txt ,文档内容即是 DisplayProcesses.vbs. 的输出结果,不相信?那么请在命令提示符中输入 notepad output.txt, 用记事本中打开新建的文档来证明一下吧。正如您将看到的那样,您现在拥有了一份最后一次运行脚本时,电脑所运行程序的永久报告。想一想,您的老板可能刚才还说您什么也没干呢!

哦,请等一下:我是说 我们的 老板。

假如您再次运行这个脚本并再次将输出定向到 output.txt ,那么新的结果会覆盖上一次存储在该文档中的结果;这是 > 符号的工作方式造成的。您可以改变这一点,将 dir 命令的输出定向到 output.txt 然后检查结果。只要输入 dir > output.txt 然后再输入 notepad output.txt。您将会发现. dir 命令的输出已经覆盖了您先前存在该文档中的程序输出信息。

这看起来很不错,但是假如您想 添加数据 而不是覆盖数据应该怎么办呢?这种情况下,就要运用 >> 重定向命令来代替它。试试吧。在提示符中输入 cscript DisplayProcesses.vbs >> output.txt 。然后输入 notepad output.txt 注意到来自dir的输出仍然存在,而来自 DisplayProcesses.vbs 脚本的输出则被添加到了文档的最末尾。

虽然外壳定向是将脚本输出保存到文档的最简易方法,但是您还是可以多次练习以掌握如何运用 FileSystemObject 将信息存入文档中。FileSystemObject 是一个存在于 Scripting Runtime Library (包括在 WSH 中)的组件,它能使您的脚本能够利用各个文档和文件夹。您可以进行复制、删除,当然也可以从中读取或是写入文本文档。

提示: 想要了解有关 FileSystemObjectWant 在更多信息吗?请参阅题为 Windows 2000 Scripting Guide 的文章。 FileSystemObject

为了介绍如何使用 FileSystemObject,我们整理一个十分简单的脚本,它创建了一个名为 fsoutput.txt 的文档, 我们在其中写入一行简单的内容。内容是一个包含有题目及创建日期和时间的标题。如下所示:

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.CreateTextFile("fsoutput.txt")
objNewFile.WriteLine "Header Information -- Date: " & Now()
objNewFile.Close

试验一下。希望您现在就了解所需的步骤:在记事本中输入脚本,然后将其以 .vbs 的扩展名进行保存(干脆就叫 CreateNewFile.vbs 吧)。输入 cscript CreateNewFile.vbs 然后再输入 notepad fsoutput.txt 来看看结果。您应该能看到如下所示的结果:

您可能会发现,将数据保存到文档中的步骤和在命令窗口中显示数据的步骤是极其相似的。虽然所得到的结果完全不同,但其间达成任务的方法却十分相似。当您向屏幕输入时您使用 WScript.Echo;而您写文档时使用的是 WriteLine 方法。不同的是一个必须要创建 FileSystemObject 的实例,而另一个是必须创建一个保存数据的文本文档,这两个步骤是相同的。

让我们使用 DisplayProcesses 脚本,修改后将其数据保存到一个文档中,而不是在命令行窗口中显示它。脚本在被修改后显示如下:

Set objWMI = _
   GetObject("winmgmts:{impersonationLevel=impersonate}//./root/cimv2")
Set colProcesses = objWMI.ExecQuery("SELECT * FROM Win32_Process")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.CreateTextFile("writeoutput.txt")
objNewFile.WriteLine "Process Report -- Date: " & Now() & vbCrLf
For Each objProcess In colProcesses
   objNewFile.WriteLine "进程名称:"    & objProcess.Name
   objNewFile.WriteLine "可执行文件的路径:" & objProcess.ExecutablePath
   objNewFile.WriteLine _
        ".............................................."
   objNewFile.WriteLine vbCrLf
Next
objNewFile.Close

运行此脚本,并看看记事本中的输出。您将看到以下内容:

提示: 这个特殊的脚本将总是覆盖 WriteOutput.txt 文档。为了向文档中添加数据,我们要打开文本文档,而不是用 CreatleTextFile 的方法创建一个新的文档。想要了解关于打开文本文档(并将数据添加到这些文档)的信息,请参阅 Windows 2000 Scripting Guide 中 将数据写入文本文件部分。

好了,现在看上去比原先在命令提示符窗口中看不清信息好多了(顺便说一句,假如 仍然 看不清,那么一定是您的显示器该清理了)。只是,要是能加上一点格式就更好了。对于这一点,一些更加结构化的格式,就像您在一些基于站点的报告工具中看到的那样,都是很不错的东西。事实上,我们也可以利用一些 HTML( 超文本链接标记语言)来组成我们 自己的 基于站点的报告工具。

虽然您不熟悉 HTML,但也不用害怕。脚本专家组将专门花 30 秒的时间来为您介绍 HTML。HTML 是一种标记语言(也就是HTML的最后两个字母所代表的含义)。为了理解标记语言的概念,您可能要编辑一篇大约1200字的文章。文章开头就是介绍这种语言大致是为了提示段落从哪里开始,哪里结束,哪里一些词字应该组成一个标题下的文章。您可能会采取一些措施来标记文章的标题,加下划线,用粗体,或 斜体 来强调一些单词和有解释性的句子。

假如您希望将一些内容突出为标题,那么您可以它用引号引起来,并标记为“Title(标题)”。有些人标记标题的方法可能会有一点不同;例如,他们可能加下划线或是直接标注为“Article Title(文章标题)”。不论用哪种方法,您都是在形成自己的标记语言。

那么您自己的标记语言和 HTML 有什么不同呢?有两点不同:1)软件程序被设计为能够诠释 HTML,2)HTML 是一种预设的标记语言,是全世界通用的。除此之外,HTML 实际 与您所设计的标记语言没有区别:只是一种将无格式文本进行格式化,使其能在 Web 浏览器上被显示的方法。

在 HTML 中,您将运用标签(通常成对出现)来标记文件。例如您为了标记顶级标题,您必须将所需内容用 <H1> 标签(这个符号表示“从这里开始,将后面所有的内容作为 H1 级的标题”)和 </H1> 标签(这个符号表示“从这里开始停止将内容作为 H1 级的标题,之后的内容返回默认设置”)括起来。因此假如您的顶级标题是 Windows Management Instrumentation,那么您就使用以下的 HTML 格式:

<H1>Windows Management Instrumentation</H1>

每一篇 HTML 文件中都有一些核心结构用于标记文件头(header)和正文。头部分包括了有关文件的各种元数据,至少应该包括标题。以下便是最小的 HTML 文件:

<html>
<head>
<title> 标题 </title>
</head>
<body>
<h1> Windows 管理规范 </h1>
</body>
</html>

尝试着将上述的 HTML 输入记事本,将其保存为以 .htm 为扩展名的文档,名字就叫 minimal.htm 吧。然后在命令提示符中输入 minimal.htm ,就可以在 Internet Explorer 中查看它了。您将看到如下所示的内容:

因此,现在您就成为了一个 Web 设计专家。假如现在是九十年代中期,那么您的下一步就可能是一个商业计划书或者一个10 亿美元的 IPO 了。但是现在我们是在21 世纪(哦,至少我们中的大多数是如此),我们最好回到工作中去,看看这一新信息是否能被充分利用。

现在,在我们开工之前,我们知道您在想些什么。您在想,“ 嗯,脚本专家们,我是一个系统管理员,可不是个 Web 开发人员。为什么你们要告诉我这些呢?我甚至连 FrontPage 都没有呢!”好吧,那就别再想我们刚才做的那些事儿了:我们用记事本创建了一个 Web 页。这是因为我们运用了一些大众无法得到的超强的 Notepad XP 吗?不是的;是因为 Web 页本身就是文本文档;这就意味着您能够使用任何一种文字编辑器,或使用一个脚本来创建它们。您根本不需要用 FrontPage 来创建那种看上去很酷的 Web 报告。

哦,请千万别告诉 Microsoft 的人您不需要 FrontPage,好吗?

好吧。让我们将 DisplayProcesses 脚本重写一遍,但这次我们将创建一个 .htm 文档和并且使用一些 HTML 标记。注意,当您运行这一脚本时,似乎什么也没有发生。这是因为我们没有将输出显示在屏幕上,而是写进了一个 HTML 文档中。

以下就是我们重写的脚本:

Set objWMI = _
   GetObject("winmgmts:{impersonationLevel=impersonate}//./root/cimv2")
Set colProcesses = objWMI.ExecQuery("SELECT * FROM Win32_Process")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.CreateTextFile("htmloutput.htm")
objNewFile.WriteLine "<html>"
objNewFile.WriteLine "<head>"
objNewFile.WriteLine "<title>Process Report</title>"
objNewFile.WriteLine "</head>"
objNewFile.WriteLine "<body>"
objNewFile.WriteLine "<h1>Process Report -- Date: " & Now() & _
    "</h1>" & vbCrLf
For Each objProcess In colProcesses
   objNewFile.WriteLine "Process Name: "    & objProcess.Name
   objNewFile.WriteLine "Executable Path: " & objProcess.ExecutablePath
   objNewFile.WriteLine _
       ".............................................."
   objNewFile.WriteLine vbCrLf
Next
objNewFile.WriteLine "</body>"
objNewFile.WriteLine "</html>"
objNewFile.Close

在运行脚本后,请输入 htmloutput.htm打开最终的 HTML 页(名称为 htmloutput.htm)。您将看到与以下内容相似的内容:

首先,看一看这个脚本运行的时间:凌晨1点!呵呵,我们最好找点别的爱好。无论怎样,这只是个开始(我们 的确 创建了一个 Web 页),但是还必须做一些工作才能使这些信息变得可读。考虑一下,这样的数据要是能在表格里就好了。我们假定:HTML 支持表格。(最好它能支持,否则我们可就结束不了这个专栏了。)

创建 HTML 表格是十分简单的,虽然头一眼看上去它有点神秘。一个表格在开始时用 <table> 标签来表示,结束时用 </table> 标签表示。表格中的行用成对的 <tr></tr> 标记,第一行中的列则用成对的 <td></td> 来标记(我们 告诉过 您它头一眼看上去有点神秘)。以下是一个简单 HTML 表格的示例:

<table>
<tr><td>1st column of 1st row</td><td>2nd column of 1st row</td></tr>
<tr><td>1st column of 2nd row</td><td>2nd column of 2nd row</td></tr>
</table>

修改我们的脚本,使其将其输出导入到一个 HTML 表格。以下是被修改的脚本:

Set objWMI = _
   GetObject("winmgmts:{impersonationLevel=impersonate}//./root/cimv2")
Set colProcesses = objWMI.ExecQuery("SELECT * FROM Win32_Process")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.CreateTextFile("htmloutput.htm")
objNewFile.WriteLine "<html>"
objNewFile.WriteLine "<head>"
objNewFile.WriteLine "<title>Process Report</title>"
objNewFile.WriteLine "</head>"
objNewFile.WriteLine "<body>"
objNewFile.WriteLine "<h1>Process Report -- Date: " & Now() & _
    "</h1>" & vbCrLf
objNewFile.WriteLine "<table BORDER=1>"
For Each objProcess In colProcesses
   objNewFile.WriteLine "<tr>"
   objNewFile.WriteLine _
       "<td>Process Name:</td><td>" & objProcess.Name & "</td>"
   objNewFile.WriteLine "<td>Executable Path:</td><td>" & _
       objProcess.ExecutablePath & "</td>"
   objNewFile.WriteLine "</tr>"
Next
objNewFile.WriteLine "</table>"
objNewFile.WriteLine "</body>"
objNewFile.WriteLine "</html>"
objNewFile.Close

请注意我们在开放的 <table> 标记中添加了 BORDER=1 。这可能正是您所期盼的,它能让表格显示边框。

当然,该表格的输出可能会有点不好理解。还有以下内容:

我们首先写下开放的表格标签 <table BORDER=1>,然后,我们就进入循环。这确保了我们只设计一个表格,且这个表格就是我们想得到的表格。在每个循环中的第一笔就是要写上 <tr> 标记,以标记新的一行。因此,我们每一次通过这个循环,我们都会重起一行。这就代表了每一次通过循环所代表的都是有关一个单独步骤的信息,而且这也是我们希望能在表格中以单独一行到显示的信息。

到现在为止,一切还都不错是吗?接下来就是完成每一行中的列了。利用一对 <td></td> 标记来将属性的名称(Process Name, Executable Path)列在同一列中,而另一组 <td></td> 标记则被用于将相应的值导入同一列中。最后,在退出循环前,我们用 </tr> 标记来结束行。

结果显示的 htm 页面应与以下相似:

它可能不能赢得什么图形设计奖项,但它却能很好地被读懂,比那些模糊且乱作一团的命令提示符输出好多了。假如您在 MSDN 和 Web 上进行查询,您将找到一大堆有关 HTML 的信息和如何制作网页的内容,看上去相当内行。我们就把那些细节上的内容留给您作练习吧。毕竟,这个专栏是系统管理脚本的,而不是网站设计。

提示: 您是对的;运行这个脚本真的是很酷,Web 页会自动地出现在屏幕上。您是怎么做到的?这有一种方法:只要在脚本末尾添上这两行就行了:

Set objShell = Wscript.CreateObject("Wscript.Shell")
objShell.Run "htmloutput.htm"

我们将结束本月的漫谈,最后要告诉您的是一种将输出导入到 Excel 的便捷方法。Excel 拥有丰富且可以编写脚本的对象模型,它能使您从脚本中创建真正够酷的电子数据表。但是,时间不早了,我们的篇幅也有限。根据脚本真正的精神所在,让我们选择一条阻力最小的道路。我们将修改我们的脚本,并将其输出到 csv(逗号分隔符) 格式,我们可以在 Excel 中打开它。

以下便是修改后的脚本:

Set objWMI = _
   GetObject("winmgmts:{impersonationLevel=impersonate}//./root/cimv2")
Set colProcesses = objWMI.ExecQuery("SELECT * FROM Win32_Process")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.CreateTextFile("output.csv")
objNewFile.WriteLine "Process Name,Executable Path"
For Each objProcess In colProcesses
   objNewFile.WriteLine objProcess.Name & "," & _
       objProcess.ExecutablePath
Next
objNewFile.Close

这个脚本是极其简单的。它输出了两个以逗号隔开的标题(Process Name 和 Executable Path),继而输出用逗号隔开的 Name 和 ExecutablePath 属性。假如您在记事本文档中将其打开,就会如下所示:

Process Name,Executable Path
System Idle Process,
System,
Smss.exe,C:/WINDOWS/System32/smss.exe

为了在 Excel (假定您的机器中已经安装了 Excel )中看到这个脚本的运行结果,请在命令提示符中输入 output.csv 。您将看到如下所示的内容:

当然,这是种“欺骗”,但是谁知道呢?毕竟,对我们而言,它看上去很像一个不错的电子数据表。

这次我们就为您讲这么多;毕竟,脚本专家们也是要睡觉的。我们希望这个专栏能是您关于输出格式试验的开始。我们仅仅了解了些皮毛,知道了您可以从脚本中的哪个地方发送输出。例如,ADO 是一种能使您向各种数据存储进行输出的技术,包括 Access 和 SQL Server,当然,XML 是当前 最流行的。 您可以轻而易举地将您的脚本输出存储在 XML 格式中(XML 也只是另一种文本文档而已),与 Windows 源代码中的分号相比,它带来了更多的可能性。

嗯,这意味着有很多种可能,因为在 Windows 源代码中有许多的分号。

在下次见面之前,停止一切幻想吧:脚本!

要获得有关脚本专栏的所有内容和附加信息,点击此处

脚本热讯!

人们常常写信给我们问,“下次有新的脚本故事或是有新脚本被添加到 TechNet 脚本中心时能通知我们吗?”我们总是告诉他们,“我们看上去像您的贴身仆人吗?”哦,现在我们的回应更有礼貌了(也更有用了)。当 TechNet 脚本中心有新成员加入时也要通知您吗?脚本界有了最新的头条新闻也要通知您吗?假如是这样的话,请您注册我们的 脚本热讯,它将每月更新,报导脚本中心及脚本领域的最新发展。点击以下链接,很快您就将通过电子邮件获得您第一期的脚本热讯(哦不,现在还没有计划开发 swimsuit 版本):

注册 脚本新闻专线

 

本文章转自:http://www.microsoft.com/china/technet/community/columns/scripts/sg0403.mspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值