启动 Script Debugger

详情见;http://hi.baidu.com/cty901/item/b6dfd6df4ece4a19d78ed0f7

Microsoft Script Debugger 是一个相当好的小工具,但正如我们所注意到的一样,它的样子有点怪怪的。我们先说说您要注意什么问题。在下载并安装 Script Debugger 后,您第一个想法可能就是启动调试器并在其中装载一个脚本。千万不要这样做,这不管用。的确,调试器会启动并且您可以 装载脚本,但此时会出现一点问题;注意,所有调试命令都是灰显的,您实际上不能执行任何操作:

 

不过说真的,要是其他 Microsoft 软件连最基本的功能都没有的话,我就不用这么累写稿子了!不要担心:Script Debugger 实际上是好用的,只是当您手动启动它并装载脚本时,它才会出现无法工作的情况。您需要从命令行启动脚本并传递参数 //x。例如,要在 Script Debugger 中装载脚本 my_script.vbs,您应该键入类似下面的命令:

cscript my_script.vbs //x

 

注意。 Script Debugger 为什么会是这样呢?我们也不知道。您可以试着问一下海豚,据说它们是非常聪明的……

实际上,这个问题的答案很可能与以下事实有关:Script Debugger 最初是为调试 ASP 和 HTML 页设计的。还有一则好消息是,此调试器还适用于独立的 VBScript 和 Jscript 文件。

不可否认,这听起来有点荒唐,但这种方法的确奏效。使用 //x 参数启动脚本后,您会发现所有调试命令现在都可以使用了:

 

重要说明。 在继续讨论之前,我们应该指出 Script Debugger 工具允许您在很大程度上控制如何运行脚本;但是,它并不是那种十全十美的环境,在运行脚本时可能会对其他程序造成影响。在使用 Script Debugger 时,脚本实际上正在运行;事实上,如果您要在工作时查看脚本输出情况,您可以使用 Alt-Tab 组合键在调试器和命令窗口之间来回切换。如果所调试的脚本可删除 Active Directory 中的所有用户帐户,您可不要将调试会话当作是彩排或演习;在会话结束时,它将会删除 Active Directory 中的所有用户帐户。该调试器是一个故障排除工具,但它并不是沙箱或某种虚拟环境。

那么,在将脚本装载到 Script Debugger 中后,该怎么办呢?虽然有几种可供选择的选项,但我们重点介绍以下任务:

 

分步执行代码

设置和删除断点

处理变量

运行脚本命令

分步执行代码

举一个软件的例子,Microsoft Word 是一个事件驱动的应用程序。在启动 Word 时,它不执行任何操作;它只是静静地等待事件的发生,等待您单击鼠标按钮或按键盘上的键或者执行某种操作。(当然了,如果等待时间过长,即使在您执行某种操作之后,它也不会做出任何响应,但这已超出了本文讨论的范围。)

与之相比,脚本通常是过程驱动的:在启动后,它们通常并不等待事件发生,而是直接运行。在脚本启动后,它运行第一行代码,然后(甚至没有停下来“喘口气”)开始运行其余的代码行,整个过程一蹴而就。在运行完代码行后,脚本就会自动终止。

只要一切正常,这就是一种很好的模型。然而,如果执行情况与计划的情况不完全一致时,此模型就会中止一段时间。例如,假定有一个用于完成以下任务的脚本:

 

在本地计算机上创建一个文本文件。

从几个服务器中检索硬件信息。

将检索到的信息写入所创建的文本文件中。

将该文本文件从本地计算机复制到远程计算机上。

从本地计算机上删除该文本文件。

您运行该脚本,一眨眼的功夫,脚本就完成了它的任务。您检查本地计算机,没有文本文件。这很正常呀!毕竟,脚本就是应该从本地计算机上删除文本文件。现在,检查一下远程计算机:也没有文本文件。麻烦了!显然,出现了问题,但到底出现了什么问题,问题出在哪里呢?即使这是一个相对简单的脚本,脚本也可能会在很多地方出现错误。我怎么能知道问题到底出在哪里呢?

 

注意。 我们假定此脚本中包含防止脚本崩溃的 On Error Resume Next。但要记住,即使删除 On Error Resume Next 也不一定能找出实际发生错误的确切位置。请考虑下面的简单脚本:

intMyNumber = 2
A = intMyNumbr
B = 3
C = B / A

如果您运行此脚本,就会在第 4 行出现错误,这是因为除数为 0。但实际上问题并不是出在第 4 行,问题实际出在第 2 行,您在该行中将变量 A 设置为 0 而不是 2。这是由于拼写错误造成的:您为 A 分配 intNumbr 的值而不是 intNumber 的值。因为 intNumbr没有 值,所以将 A 赋值为 0,而不是您希望分配的 2。

不可否认,这是一个很容易找出来的错误。但问题的关键是,在脚本崩溃时显示的错误信息只告诉您错误在哪一行中显现了出来;也就是说代码中的错误在哪一行中实际引发了错误。错误的根本原因(如将变量设置为 0)可能在数百行代码之前就已经存在了。

处理此类问题的一种方法是使用 Script Debugger 来“分步执行”代码。分步执行代码即逐行运行脚本。不可否认,如果脚本很长,这可能会是一项冗长而乏味的工作;不过,我们一会将向您介绍一种解决方法。另一方面,通过分步执行代码,您可以在每一步停下来并确保脚本正常工作。

例如,我们假定的脚本在运行时首先应该创建一个文本文件。在我们按原样运行脚本时,我们不知道是否在第一个地方创建了文本文件。但通过分步执行代码,我们就可以非常方便地验证这一点。我们运行将创建文本文件的代码行,然后停止。随后,我们打开 Windows 资源管理器并检查文本文件是否存在。如果文件存在,则继续分步执行脚本的其余部分。如果文件不存在,则我们就已找到了一处错误。

那怎么在 Script Debugger 中分步执行代码呢?实际上这是非常容易的:在调试器中装载脚本,然后按 F8 键。每次按 F8 键时,调试器将执行一行代码,跳到 一行代码,然后等待您再次按 F8 键。(顺便说一句,如果您不喜欢使用键盘,您也可以从Debug(调试)菜单中选择 Step Into(单步执行))。一直按 F8 键,直至到达脚本的结尾。您也可以从当前行开始运行脚本的其余部分。为此,请按 F5 键或者从Debug 菜单中选择 Run(运行)。

 

警告。 假定您调试的脚本从事件日志中检索事件,并且假定这些事件日志中有 5,000 个事件。在分步执行使用 For Each 循环的代码时一定要小心;脚本不只运行该循环一次,它将运行 5,000 次,为集合中的每一项分别运行一次。对于此类情况,您可能只需要运行循环一次或两次(只为确认循环运行是否正常),然后按 F5 键以运行脚本的其余部分。或者,您也可能需要使用断点,我们稍后将对其进行介绍。

最后一步

还有最后一件怪事,我得提醒您一下。您已经运行了一遍脚本并且一切正常。但小心不会出大错,对吧?因此,您希望再运行一次脚本,这样才会安心。没有问题。但您必须退出 Script Debugger 并重新装载脚本,否则就可能会出问题。由于某种原因,您只能在 Script Debugger 中运行脚本一次;在完成后,您需要退出调试器并重新启动。

知道了,知道了。别生气,我们也不认为这是一种特别好的做法;事实上,我们开始怀疑,与其说人类灭绝了非洲蓝羚羊,倒不如说软件的用户界面设计离奇古怪。但至少我们已经向您说明了 Script Debugger 的怪异之处;可怜的非洲蓝羚羊怕是永远也看不到这一天了。

设置和删除断点

假定您的脚本有 1,000 行,并且您系统地分步执行了代码(逐行执行)。一切似乎都很正常,但在第 933 行发现了一处错误。您停止了调试器并更正了脚本错误。现在,您需要重新在调试器中装载脚本并再次运行,但您确实不想再重新执行一遍前 932 行。不管怎么说,您都非常确定这些代码行没有什么错误。但除了重来一遍,您还有什么选择吗?

如果您是新喀里多尼亚岛的乌鸦,那就一点选择都没有了。作为人,您比它们可要聪明多了,您可以走捷径呀,即在第 933 行设置一个断点。您可能会问,什么是断点?从用途上来讲,断点就像插入到代码中的“停车标志”。如果您在 Script Debugger 中运行脚本(通过按 F5 键或从Debug 菜单中选择 Run),脚本将一直运行至断点处,此时它会“嘎然停止”。您可以从此处开始分步执行代码,也可以选择Run 来运行脚本的其余部分。

在 Script Debugger 中,您可以非常容易地识别出断点。事实上,它们与下图中的情形非常类似:

 

注意以红色突出显示的内容和类似停车标志的小红图标。

那怎么设置断点呢?只需将光标放置到到目标行的任何地方,然后按 F9 键(或者从 Debug 菜单中选择 Toggle Breakpoint(切换断点))。要删除断点,请再次按 F9 键,或者按 Ctrl-Shift-F9 组合键删除脚本中的所有断点。

您可能已经猜到了,断点是逐行分步执行代码的一个很好的替代方案。您确信脚本的前 932 行都是正确无误的吗?没问题;那只需在第 933 行设置一个断点并运行脚本即可。脚本将快速通过所有这些行,直至到达断点处;然后突然停止。此时,您可以开始分步执行代码的其余部分。

 

处理变量

正如前面所提到的一样,变量被设置为错误值或意外值这一问题是脚本中经常出现的错误。更糟的是,此类错误可能很难找出来,尤其是在较长的脚本中,其中的变量值可能会改变很多次。那到底怎么才能在运行脚本时跟踪变量的当前值呢?

一种方法是在 Script Debugger 中分步执行脚本,并定期向调试器查询变量的当前值。有没有更简单的方法呢?

让我们使用一个很简单的脚本来试一试。以下脚本(我们保存为 Test.vbs)为变量 A 赋值 2,并为变量 B 赋值 3。然后脚本执行一些计算,并将这些计算的累积结果分配给变量 C。脚本本身类似于以下内容:

A = 2
B = 3
C = A + B
C = C * A
C = C^B
Wscript.Echo C

如果您运行此脚本,返回的答案应该为 1000。好极了,是吧?但是,1000 到底是不是您应该得到的答案呢?谁知道呢?更糟的是,您到底如何才能开始确定这是不是正确答案呢?

您可以做的一件事是在 Script Debugger 中装载脚本,分步执行代码,然后定期向调试器查询以了解各个变量的值。请执行以下操作:在 Script Debugger 中装载脚本,并分步执行前三行代码。突出显示的位置应该是C = C * A,屏幕显示应类似于以下内容:

到现在为止,我们的脚本运行情况如何?我们可以从这里开始进行复核。我们知道 A 等于 2,B 等于 3,我们刚刚执行了等式 C = A + B 的运算。换句话说,C = 2 + 3,这就是说 C 应该等于 5。我们 知道这一点,但我们的脚本 是否知道呢?

好,让我们来问问它。在 Script Debugger 中,从 View(视图)菜单中选择 Command Window(命令窗口)。您现在应该看到一个类似于此屏幕内容的小窗口:

我们可以通过命令窗口与脚本进行交互;我们可以向它提问题,正如我们稍后会看到的,我们甚至还可以使用它来向脚本发出命令。我们先使用问号 ? 作为命令,查询一下变量 C 的当前值:

? C

换句话说,在命令窗口中键入 ? C,然后按 Enter 键;您会立即获得变量 C 的当前值。

不错吧?现在,按 F8 键执行下一行代码 (C = C * A)。我们知道 C 等于 5,而 A 等于 2;因此,在运行此代码行后,我们预计 C 应该等于 10 (5 * 2)。因此,让我们使用命令窗口再看一下变量 C 的当前 值:

好家伙,我们这不得做上一天呀!执行下一行代码 (C = C^B)。在此代码行运行后,C 应该等于 1000 — 10(C 的当前值)的 3 次幂(因为 B 等于 3)也就是 1000。您猜呢?

有没有更好的办法呢?

运行脚本命令

那么,与在脚本运行时查询脚本并获取有关脚本所执行操作的信息相比,到底有没有 更好的办法呢?没有,当然没有,除非您能在脚本运行时真的向其发送命令。但这是很荒谬的;在脚本运行时无法向其发送命令。难道真的能行……

让我们看另一个简单的小脚本,它返回有关 Internet Explorer 附加组件的信息:

strComputer = "atl-ws-01"
Set objWMIService = GetObject("winmgmts:\\" & strComputer _
    & "\root\cimv2\Applications\MicrosoftIE")
Set colIESettings = objWMIService.ExecQuery _
    ("Select * from MicrosoftIE_Object")
For Each strIESetting in colIESettings
    Wscript.Echo "Code base: " & strIESetting.CodeBase
    Wscript.Echo "Program file: " & strIESetting.ProgramFile
    Wscript.Echo "Status: " & strIESetting.Status
Next

正如所编写的一样,此脚本连接到远程计算机 (atl-ws-01),然后从 MicrosoftIE_Object 类中检索某些信息。又是老一套,是吧?我们想通过在 Script Debugger 中分步执行来测试此脚本,因此,我们装载此脚本,按 F8 键运行第一行代码,该行将变量 strComputer 的值设置为 atl-ws-01。

但是,此时我们意识到有一个问题:我们突然想起计算机 atl-ws-01 没有联机。因为我们无法连接到该计算机,所以脚本注定会失败。您一定以为我们必须退出 Script Debugger,更改脚本(将其指向另一台计算机),然后重新运行脚本,是吧?

错。脚本有问题吗?问题是出在我们要连接到由变量 strComputer 表示的计算机。这没有什么问题,只是 strComputer 的值当前为 atl-ws-01,而该计算机没有联机。但您知道吗?实际上,这并不是 什么问题。在我们运行用于连接到远程计算机的代码行之前,我们只需要将 strComputer 的值更改为已联机的 某台计算机即可(例如,我们可以将 strComputer 更改为“.”以便针对本地计算机运行脚本)。您猜该怎么做?是的,这次您说对了,我们就是在命令窗口中做到这一点的:

只需在命令窗口中键入相应的命令并按 Enter 键;果不其然,脚本中的 strComputer 的值将更改为圆点 (.)。这真的 很棒!

您也可以输入更复杂的命令。例如,请考虑以下脚本,它用于返回本地计算机上安装的所有服务的名称:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer _
    & "\root\cimv2")
For Each objItem in colItems
    Wscript.Echo "Name: " & objItem.Name
Next

非常棒,是吧?美中不足的是缺少了一行代码,该行代码实际上从 Win32_Service 类检索信息。该脚本应该 类似于以下内容:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer _
    & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
    ("Select * From Win32_Service")
For Each objItem in colItems
    Wscript.Echo "Name: " & objItem.Name
Next

不过,没有关系。只需在 Script Debugger 中装载脚本,并分步执行前两行代码。在到达缺少的第三行代码时,不要慌;在命令窗口中键入缺少的代码行,然后按Enter 键:

只需从此处单步执行该代码,脚本就会报告本地计算机上安装的所有服务的名称,这与预想的一模一样。

 

脚本专家的绝学秘笈

现在告诉您一个真正 精彩的内容。命令窗口被设计为每次运行一行代码;您键入命令,按 Enter 键,就会执行该行代码。这的确不错。但假使您遗漏了 行代码,并且忘了加上 For Each 循环。您一定会想:“没有关系,我逐行键入缺少的代码不就行了。”诚然,有些时候的确可以。但在此处,当您键入缺少的第一行代码,然后按Enter 键,就会发生以下情况:

到底出了什么问题?问题出在您创建了 For Each 循环,但没有 Next 语句(之所以没有 Next 语句,是因为您还没来得及键入呢)。因为命令窗口只处理单行代码,所以您无法键入 Next 语句;在您达到该行代码之前,早就产生错误了。看似您运气不好,对吧?

又错了。实际上,VBScript 允许在一行中键入多行代码,前提是您使用冒号 (:) 来分隔各个行。例如,我们可以将整个 For Each 循环放在一行代码中(如下所示):

For Each objItem in colItems:Wscript.Echo "Name: " & objItem.Name:Next

对,您想到我们前面去了:如果在命令窗口中键入 字符串并按 Enter 键,就会执行所有三行代码:

您会用到这些东西吗?可能不会。但我要重申的是,几个月前您会想到您会需要与脚本有关的工具 吗?

 

结束语

作为人类的一员,我不愿承认,但我不得不说我们可能永远也无法摆脱电脑虫的纠缠。加州秃鹰如何?对,我们是可以将加州秃鹰赶尽杀绝。但电脑虫呢?绝对不可能;它们实在是太多了。

另一方面,单单因为虫子种族不能根除,还不足以说明我们不能追踪并消灭虫子个体,尤其是潜伏在我们脚本内部的那些虫子。如果我们可借助于诸如 Microsoft Script Debugger 之类的工具,那我们还等什么呢?总之,如果那些电脑虫可以使用此类工具来对付我们,后果可就不堪设想了……试一下 Script Debugger,告诉我们您的感受。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值