您好,脚本专家!

您好,脚本专家!

欢迎来到本 TechNet 专栏,在这里,Microsoft 脚本专家将为您解答与系统管理脚本编写有关的各种常见问题。遇到了系统管理脚本编写方面的问题?请将电子邮件发送到 scripter@microsoft.com。我们不能保证回答收到的所有问题,但是我们将尽最大的努力。

同时,不要忘了查看您好,脚本专家!存档

今日问题:如何将文本文件打印到默认打印机之外的打印机?


如何将文本文件打印到默认打印机之外的打印机?

问:

您好,脚本专家!如何将文本文件打印到默认打印机之外的打印机?

-- JD

答:

您好,JD。伙计,谈谈骄兵必败吧。当我们开始着手回答此问题时,我们已经“知道”如何解决问题了。我们清楚地知道,Shell 对象为您提供了一种将文本文件打印到默认打印机的方法;我们还清楚地知道,该默认打印机是您能打印文本文件的唯一打印机。不过,作为脚本专家,我们认为我们对此问题有一个聪明的解决方法:我们会告诉每个人使用 Microsoft Word 来打印文本文件。然后我们会休息一下,倾听大家夸我们是多么的聪明。

天哪。只有当我们开始详细编写答案后,我们才真正地费神去检查并查看 Microsoft Word 是否确实允许您在通过脚本打印文档时选择其他打印机。事实证明,它不允许这样做:Word 也要求您打印到默认打印机。不得不承认,脚本专家错了

注意:对,是这样的:我们错了许多次了。但这并不能减轻任何痛苦。

正如您所料,这就是骄傲:我们不得不寻找一种方法来将文本文件打印到其他打印机。遗憾的是,我们找不到这样一种方法。因此,我们决定采用第二种方案:如果我们只能打印到默认打印机,那么我们就只更改默认打印机,打印完文件后再改回来。以下为在 Windows XP 和 Windows Server 2003 下奏效的解决方案:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Default = TRUE")

For Each objPrinter in colPrinters
    strOldDefault = objPrinter.Name
    strOldDefault = Replace(strOldDefault, "\", "\\")
Next

Set colPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer2'")

For Each objPrinter in colPrinters
    objPrinter.SetDefaultPrinter()
Next

Wscript.Sleep 2000

TargetFolder = "C:\Logs" 
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(TargetFolder) 
Set colItems = objFolder.Items
For Each objItem in colItems
    objItem.InvokeVerbEx("Print")
Next

Set colPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Name = '" & strOldDefault & "'")

For Each objPrinter in colPrinters
    objPrinter.SetDefaultPrinter()
Next

注意:为何仅限于 Windows XP 和 Windows Server 2003 呢?是这样,之前的 Windows 版本不易识别和更改默认打印机;这是因为 WMI 类 Win32_Printer 既没有 Default 属性也没有 SetDefaultPrinter() 方法。因此,我们决定今天讨论 XP/2003 解决方案;如果您对 Windows 2000 版本有足够的兴趣,那好,我们来看看我们会得出什么样的结果。

不可否认,此脚本看起来可能稍微有点复杂;请宽容我们吧,尽管如此,您还是会看出我们要执行的操作以及为何执行这些操作的。我们首先连接到本地计算机上的 WMI 服务,然后检索默认打印机的 Name。这就是下面的代码所要执行的操作:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Default = TRUE")

For Each objPrinter in colPrinters
    strOldDefault = objPrinter.Name
    strOldDefault = Replace(strOldDefault, "\", "\\")
Next

此段代码的第一部分应该很好理解;唯一稍难理解的部分在于我们的 WQL 查询。我们仅需要默认打印机的信息,因此我们构造了一个查询,该查询可返回 Default 属性等于 True 的打印机的数据。由于计算机上只能有一台默认打印机,因此,此查询应该只返回一台打印机。

代码段的第二部分(For Each 循环)可能需要多费一些口舌。在 For Each 循环中,我们检索默认打印机(请记住,该默认打印机是集合中的唯一打印机)的 Name 并将其存储在名为 strOldDefault 的变量中。至此不会有什么问题。接下来是下面这行代码:

strOldDefault = Replace(strOldDefault, "\", "\\")

为什么呢?是这样,如果默认打印机恰好为网络打印机,它将具有类似下面的名称:\\atl-ps-01\printer1。这并没有什么问题,只是稍后我们需要在脚本的 WQL Where 子句中使用该打印机名称。由于 \ 为保留字符,因此我们必须通过使用两个 \ 字符来“转义”每个 \ 字符;换句话说,我们的打印机(用于 Where 子句)的名称必须为 \\\\atl-ps-01\\printer1。我们使用 VBScript 的 Replace 函数来用一对 \ 替换打印机名称中的每个 \。

您清楚了吗?好的。接下来我们使用下面的代码块:

Set colPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer2'")

For Each objPrinter in colPrinters
    objPrinter.SetDefaultPrinter()
Next

Wscript.Sleep 2000

在此,我们将请求一个新的集合,该集合中包含名称为 \\\\atl-ps-01\\printer2(注意成对出现的 \)的所有打印机;正如您所料,这就是我们要进行打印的打印机。我们检索此集合(该集合将再次仅具有一个成员),然后使用 SetDefaultPrinter() 方法使 \\atl-ps-01\printer2 成为默认打印机。然后,我们将脚本暂停两秒钟,只是为了确保更改得以进行。

既然我们有了一个新的默认打印机,我们即可继续向下进行并打印我们的文本文件。我们已直接从“您好,脚本专家”专栏中引用了以下代码,即打印文本文件中的代码。在这,我们将不再讨论该代码;如果您需要了解详细信息,请参阅有关打印文本文件的专栏:

TargetFolder = "C:\Logs" 
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(TargetFolder) 
Set colItems = objFolder.Items
For Each objItem in colItems
    objItem.InvokeVerbEx("Print")
Next

那么,到目前为止,我们都做了些什么呢?是这样,我们已确定了默认打印机的名称(对于此讨论,我们假定它为 \\atl-ps-01\printer1),并将其存储在了名为 strOldDefault 的变量中。我们已将默认打印机更改为 \\atl-ps-01\printer2 并打印了我们的文本文件。现在,我们必须要做的就是还原原来的默认打印机,我们使用下面的代码块来实现此操作:

Set colPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Name = '" & strOldDefault & "'")

For Each objPrinter in colPrinters
    objPrinter.SetDefaultPrinter()
Next

正如您所看到的,在此我们连接到了原来的默认打印机;即我们请求了一个集合,该集合包含了 Name 属性等于存储在变量 strOldDefault 中的值的所有打印机。获取该集合后,我们使用 SetDefaultPrinter() 方法将 \\atl-ps-01\printer1 重置为默认打印机。最终结果为:我们将我们的文本文件打印到了 printer2,而 printer1 仍为默认打印机。它可能不是特别聪明的解决方案,不过很有效。

而且,我们已经汲取了有关试图太过聪明的教训。我们承诺永远不再试图和真正地耍小聪明了(这是一条我们可能会信守的承诺)。


更多信息

欢迎访问您好,脚本专家!- 存档

返回页首返回页首