您好,脚本专家!言词要谨慎

Microsoft 脚本专家

美国内战期间(准确地说,是在 Spotsylvania 战役中),盟军将军 John Sedgwick 沮丧地发现这样一个事实:他的士兵被偶尔来自联邦狙击手的流弹吓得东躲西藏。据传,Sedgwick 曾这样对他的士兵说:“你们这样逃避,我真为你们感到羞耻。在这个距离,他们连一头大象也不可能击中。”过后不久,Sedgwick 即成为战争中被打死的官阶最高的盟军军官。也许在那个距离,联邦军狙击手无法击中一头大象,但不幸的是,对 Sedgwick 而言,他们却可以击中一位将军。

毫无疑问,故事所传达的道理是(你已经提到了):“如果有人向你开枪,请把头低下”,这是一种很好的精神,不是吗?我们认为这是一种很不错的做法。我们还要提倡如下精神:“言词要谨慎,因为有一天它可能会回来,成为您的困扰。”对于 John Sedgwick 将军来说,这种情况真的发生了,对许多其他人也会如此。例如,人们记得 Thomas Watson,并不因为他曾是 IBM 的总裁,美国历史上伟大的企业家。而是因为他说过的这句话,“我认为全球大概只需要五台计算机就足够了。”

有趣的是,并没有证据表明 Watson 确实说过这段话;充其量,他只是提到了其他人对这个问题的看法。但谁真正在意呢?毕竟,IBM 的总裁可能说过计算机没有市场,让我们得到一个深刻的教训,我们不能让貌似正确的愚蠢观点来妨碍我们,对吗?

顺便说一下,Watson 确实说过“迈向成功的最快方法,是把失败率提高一倍。”这是脚本专家们深信不疑的忠告。

尤其是把失败率提高一倍的忠告。

接下来,是这段引用:“如果您正在编写 VBScript 脚本,那么您就无法访问 .NET Framework。”无可否认,与“在这个距离,他们连一头大象也不可能击中”或“我认为全球大概只需要五台计算机就足够了”相比,这段说明脚本专家无法访问 Microsoft® .NET Framework 的话不太容易让人记住,但是,这种说法同样是大错特错。.NET Framework 实际上是由 C# 和 Visual Basic® 语言的开发人员设计而成的,而且 VBScript 并不能实例化原生 .NET Framework 类。但这并不意味着脚本专家就无法访问 .NET Framework,至少可以访问其部分内容。

是的,您说对了:我们不能否认对于 VBScript 来说,大多数 .NET Framework 类是无法访问的。但是,也有相当大数量的 .NET 类具有可调用 COM 的包装程序,这就意味着这些类包含一个 COM 接口,使得脚本语言(如 VBScript)可以访问它们。您说这让人难以置信?那么看一看图 1 中显示的您注册表中的 HKEY_CLASSES_ROOT 部分;您应该能够看见随系统开始的所有类。

图 1 注册表中的系统类

图 1** 注册表中的系统类 **(单击该图像获得较大视图)

这些多数是 .NET Framework 类,其中大部分都可以通过 VBScript 来实例化。

我们曾在之前谈论过这一点!

当然,正如曾经购买过深夜电视广告产品的人所证实的一样,您可以做某事并不意味着就应该做(这是通常为什么某些商品没有现货的原因)。当然,您可以在脚本中创建 System.ContextMarshalException 类的实例,我们只是不知道您为什么要使用它或者如何使用它。

但并非所有 .NET Framework 类都是如此。例如,脚本编写领域中很让人困扰的一个问题,是没有一种简单的方法来对项目列表进行排序。要将列表按字母顺序排序,要求您使用未连接记录集或完全自行创建一个深奥的排序函数,如以下冒泡排序代码(不具备这种能力的人可能想要跳到下一段):

For i = (UBound(arrNames) - 1) to 0 Step -1
    For j= 0 to i
        If UCase(arrNames(j)) > 
          UCase(arrNames(j+1)) Then
            strHolder = arrNames(j+1)
            arrNames(j+1) = arrNames(j)
            arrNames(j) = strHolder
        End If
    Next
Next

别灰心:我们编写了代码,但是我们也不完全确定它的意思。

那么,在这种情况下,.NET Framework 如何来帮助我们呢?要回答这个问题,让我们看一小段非常简单明了的脚本:

Set DataList = CreateObject _
      ("System.Collections.ArrayList")

DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"

DataList.Sort()

For Each strItem in DataList
    Wscript.Echo strItem
Next

正如您所看到的,我们是在创建一个 .NET Framework 类 System.Collections.ArrayList 的实例。然后,我们使用 Add 方法向列表中添加五个项目。这的确不错,除了一点:我们以随机的方式(B、C、E、D、A)来添加这些项,但我们需要按字母顺序(A、B、C、D、E)来显示它们。该使用冒泡排序代码了,对吗?

错了!(请原谅我们直言不讳,但是必须承认错误这个事实。)事实证明,我们不需要使用冒泡排序代码;我们所要做的是调用数组列表的 Sort 方法:

DataList.Sort()

就是这样。利用这一行代码,我们就可以对数组列表中的所有项进行排序。

证明一下?哇,这么多人。没问题;我已经料到听众里会有一些人持怀疑态度。这就是为什么脚本会包括 For Each 循环的原因,它遍历列表中的所有项,将每项的值回显到屏幕上:

For Each strItem in DataList
    Wscript.Echo strItem
Next

现在,有一个问题需要你们解决:运行该脚本时,我们会得到什么返回结果?

猜得好:

A
B
C
D
E

很不错,不是吗?

嗯,我们看到你们中的一些人还不完全满意。你们都表示这很不错,但你们真正要做的是以降序回显这些值;即,需要一个从 Z 到 A 而不是从 A 到 Z 的列表。如果你们无法获得这种结果,那么......

嗨,没问题。你们只要提问即可:

Set DataList = CreateObject _
      ("System.Collections.ArrayList")

DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"

DataList.Sort()
DataList.Reverse()

For Each strItem in DataList
    Wscript.Echo strItem
Next

你们说对了:这与我们刚才向你们展示的脚本非常相似,是吗?但是,有一个重要的补充。看一看我们在紧接着 Sort 方法的位置添加的单行代码:

DataList.Reverse()

看到了吗?在对列表进行升序排列后,我们调用 Reverse 方法,该方法将数组中的所有项逆序排列,这简直令人难以置信。它提供给我们什么?它提供给我们如下所示的输出:

E
D
C
B
A

这真得让人为之一振,不是吗?

但是等等!我们还能做得更好。你们尝试过从 VBScript 数组中删除一项吗?不要大声喧哗;我们不打算要你们这么做。我们将向你们展示从 .NET Framework 数组列表中删除一个项目是多么容易。不喜欢字母 D?去掉它。以下是创建数组列表、对其进行排序然后删除条目 D 的脚本:

Set DataList = CreateObject _
  ("System.Collections.ArrayList")

DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"

DataList.Sort()
DataList.Remove("D")

For Each strItem in DataList
    Wscript.Echo strItem
Next

你们应该再次看看紧接在 Sort 方法后的小行代码:

DataList.Remove("D")

此处我们使用了 Remove 方法来删除等于 D 的项。以下是运行脚本时获得的返回结果:

A
B
C
E

再见,D!

并且不要忽略了最精彩的一点:我们可以在不必调整数组大小或重新设置其维数的情况下删除项目。这很酷。当然,我们也可以不必调整数组大小或重新设置其维数就向数组添加项。还有什么地方没让您的脚本编写更加简单快捷呢?

信不信由你,这里只涉及了你们可以对 .NET Framework 数组列表所做的一小部分操作(有关详细信息,请参阅 .NET Framework SDK 中的数组列表条目)。

数组列表对脚本程序有用吗?让我们这样来解释一下:看过 .NET Framework 数组列表后,我们不清楚你们为什么要使用内置 VBScript 数组,至少不应用于我们在此处使用过的简单项目列表。

无可否认,我们脚本专家没有对 .NET Framework 做详尽的调查以了解哪些类可能对脚本程序有用(以及哪些可能没有用)。这项工作正在进行之中。同时,请随意浏览整个 .NET Framework SDK。似乎每次浏览 SDK 时,我们都能发现一些有趣的新东西可供脚本编写者使用。

举个例子?生成随机数怎么样?要使用 VBScript 随机数生成器生成一个 1 到 100 之间的随机数吗?没问题,只需使用类似以下的代码:

Randomize
Wscript.Echo Int((100 - 1 + 1) * Rnd + 1)

记住那个公式了吗?如果没有,别担心;事实证明,使用 .NET Framework System.Random 类要简单直观得多:

Set objRandom = CreateObject("System.Random")
Wscript.Echo objRandom.Next_2(1,100)

你们很可能不需要解释说明就能计算出结果。无论怎样,我们将提供给你们一个简短的说明,只因为 TechNet 杂志认为专栏作家每个月应该实际写些东西。(如果非得问个为什么,那我只能说这是他们的策略,不是我们的。)

正如您所看到的,我们创建了一个 System.Random 的实例,然后传递两个参数来调用 Next_2 方法:

  • 1,范围内的第一个数(记住,我们希望生成一个 1 到 100 之间的随机数)。
  • 100,范围内的上限数。

这就是我们所要做的一切。

似乎我们还有时间来回答最后一个问题。穿绿衬衫的这位。到底是谁说脚本编写者无法访问 .NET Framework?这个,坦白地讲,我们刚开始的时候 – 天哪,好象时间已经到了。下个月见!

万事顺利,万事顺利

二月份快要到了,这只意味着一件事。不,不是情人节。不,也不是总统日。噢,天哪,土拨鼠节?不,越接近二月,2007 年冬季脚本编写比赛就离我们越近,这是全球最重要(可能也是世界上唯一的)的国际脚本编写竞赛。本年度的比赛将会比以往规模更大、水平更高,这次,我们将比赛分为四个部分:

  • 初级 VBScript
  • 高级 VBScript
  • 初级 Windows PowerShell™
  • 高级 Windows PowerShell

有关详细信息,请访问 2007 冬季脚本编写游戏主页

那是什么?噢,谢谢。同时,也祝你们土拨鼠节快乐。

今天就下载 Windows PowerShell

Windows PowerShell 1.0 现在可供下载。并且是免费的!你们怎么能拒绝呢?下载该软件,今天就开始使用。

Microsoft 脚本专家为 Microsoft 工作,也就是说受雇于 Microsoft。在没有玩/指导/观看棒球(及其他各种娱乐活动)时,他们会管理 TechNet 脚本中心。要查找所需信息,请登录网站 www.scriptingguys.com

© 2008 Microsoft Corporation 与 CMP Media, LLC.保留所有权利;不得对全文或部分内容进行复制.