嗨,Scripting Guy!

嗨,Scripting Guy!

歡迎使用 TechNet 專欄,Microsoft Scripting Guys 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

還有,別忘了瞧瞧全新經過改良的嗨,Scripting Guy!過往文件

今天的問題:如何指定將文字檔案列印至非預設的印表機?


如何指定將文字檔案列印至非預設的印表機?

嗨,Scripting Guy!如何指定將文字檔案列印至非預設的印表機?

-- JD

JD,您好。這讓我想起失敗前的驕傲。還沒下筆回答,我們已經「知道」怎麼解決問題了。我們很清楚 Shell 物件是將文字檔案列印至預設印表機的一種方式,也知道這是您能夠列印文字檔案的唯一印表機。身為無所不能的 Scripting Guy,我們找出了一個聰明的解決辦法:使用 Microsoft Word 來列印文字檔案,然後只要輕鬆地往椅子上一躺,享受眾人的讚賞就得了。

真糟糕。著手答覆讀者問題時,我們才檢查 Microsoft Word 是否真的能夠在利用指令碼列印文件時,允許您選取其他的印表機。結果不行:Word 也規定必須使用預設印表機列印,發現並面對事實真令人難過,Scripting Guy 錯了。

附註:好啦,我們出錯不少次,但並不表示對痛苦的感受就遲鈍了。


讀者應該感覺得出來,這已經演變為意氣之爭了。我們一定要找出方法,把文字檔列印製不同的印表機,但的確沒有辦法。所以就採行「B 計畫」:既然只能在預設印表機列印,山不轉路轉,那乾脆修改預設印表機,列印檔案後再改回來。下面的方法可以應用在 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 改成預設印表機。接著將指令碼暫停執行兩秒,確定方才的變更已經生效。

這樣就有預設的印表機,可以列印文字檔案。這篇指令碼取自嗨,Scripting Guy!專欄中先前發表關於列印文字檔案的文章。本文不就下面的指令碼深入說明,如需進一步資訊,請參閱列印文字檔案的專欄:

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。這個方法或許不是最聰明的,但至少能用。

而且我們也因為太聰明而學到了教訓,下回不敢再耍聰明了 (這個承諾我們應該能守)。


如需詳細資訊

查看嗨,Scripting Guy!- 過往文件

 

回到頁首 回到頁首