Power Shellでプリンタをインストール
前回WindowsのPower Shellの基本的な設定と、ファイアウォールの変更してみました。今回はファイアウォール同様に利用しているPCが多くなると設定の手間が増えるプリンタの管理を、Power Shellのスクリプト化したいと思います。
Microsoft 「Docs Windows でのプリンターの操作」を参考にPowerShellでプリンタを操作してみます。
環境はWindows10です。PowerShellのバージョンは5.1でしたが、これを機に執筆時点のLTSの最新版である7.2にアップデートしました。
Power Shellのバージョン確認とアップデート
まずPowerShellのバージョンを確認します。バージョンは$PSVersionTableという変数に含まれているので読み出します。
PS C:¥> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.19041.1682
PSEdition Desktop
..
アップデートファイルはGitHubに存在しますので、環境にあったものをダウンロードします。
今回は長く運用したいのでLTSがついた最新の64bit(x64)、Windowsインストーラー.msiをダウンロードしました。(7.2.6)
msi版でインストールするとデフォルトではc:¥Program Files¥PowerShell¥7¥pwsh.exeにインストールされます。
Windows10にバンドルされているものはsystem32¥WindowsPowerShell¥v1.0¥powershell.exeにあり、複数のバージョンが同居した状態となります。
旧バージョンを立ち上げる場合はpowershell、新バージョンはpwshと打ち込むことで環境を切り替えられるようです。
PS C:¥> powershell Windows PowerShell # これ以降はプリインストール版のシェルで実行されます ... PS C:¥> pwsh PowerShell 7.3.4 # これ以降は新たにインストールしたシェルで実行されます ...
基本的なコントロール
インストールされているプリンタの一覧を確認するには次のようにします。
PS> Get-CimInstance -Class Win32_Printer
WScript.NetworkというCOMオブジェクトからも表示させることができます。
(New-Object -ComObject WScript.Network).EnumPrinterConnections()
さらに、WScript.Networkを使えば、ネットワーク上の共有プリンタを追加することもできます。
(New-Object -ComObject WScript.Network).AddWindowsPrinterConnection("¥¥サーバー名¥プリンタ名")
通常使うプリンタの設定はWMI経由で行うことができます。
指定するプリンタオブジェクトをプリンタ一覧を表示したのと同じコマンドを使って変数に取得した後、そのプリンタ変数を引数にコマンドを実行しています。
$printer = Get-CimInstance -Class Win32_Printer -Filter "Name='プリンタ名'"
Invoke-CimMethod -InputObject $printer -MethodName SetDefaultPrinter
また通常使うプリンタの指定はWScript.Networkからも行えます。
(New-Object -ComObject WScript.Network).SetDefaultPrinter('プリンタ名')
ネットワーク上の共有プリンター接続を削除するには次のようにします。
(New-Object -ComObject WScript.Network).RemovePrinterConnection("¥¥サーバー名¥プリンタ名")
プリンタドライバのインストール
今度はQuiita:「Powershellでプリンターをインストール(概要)」を参考に、プリンタのインストールやポートの設定をしてみたいと思います。
Windowsでは、ドライバとポートの組み合わせがひとつのプリンタオブジェクトとして保存されています。プリンタドライバーのインストーラーを利用するとこれらを一度に行うことがおおいですが、PowerShellで管理する場合はそれぞれ別で設定します。
まずは利用するドライバをダウンロードしてきます。自己解凍形式(インストーラー)になっているものは7Zipなどのアーカイバ―を使って展開します。
その中にINFファイルがあるので、パスを覚えておきます。
INF内にWindowsのバージョンやアーキテクチャ別にドライバ名が記述されているので、名前を覚えておきます。ドライバ名の箇所が「%変数名%」となっていたら、同じファイル内で変数定義している場所からドライバ名を取得します。
INFファイルはアーキテクチャ別に分かれていたり、プリンタとFAXやスキャナで別々のものが用意されていたりすることもありますので注意して選択してください。
;コメント等で対象のアーキテクチャ等が照会されていると思います。 [セクション] ドライバ名=.... %変数名%=... ... ;変数定義 [Strings] %変数名%=ドライバ名 ...
プリンタドライバのインストールはManagementClassから、行います。
これは.NETのAPIになるので、.NETが存在しないようならダウンロードしてインストールします。
WMIはCIMクラスのインスタンスの変更を監視してPCの変更指示に変換します。
ドライバの管理ではそのようなクラスであるWin32_PrinterDriverクラスを用います。
ポートの設定
ポートは「Win32_TcpIpPrinterPort」クラスを指定して操作します。
近年のWindowsでは9100番ポートを使った通信(Standard TCP/IP Portを使った通信)で、プリンタデータを送る事が多いです。これはRawという表記になっています。
従来からのネットワークプリンタ用のプロトコルLPR(LPD)を利用する場合は、ポート番号はは515(TCP)となります。
USBプリンタの場合は接続するとUSB001やUSB002といった仮想のプリンタポートが自動生成されますので、ポートの設定は不要です。
プリンタの登録
ドライバを追加してポートを作成しただけでは「プリンタとスキャナー」の画面の一覧には出てきません。そこでWin32_Printerクラスを用いてプリンタを生成します。
コーディング
次のコードに必要事項をいれ、管理者権限で実行するとプリンタドライバをインストールしポートを設定した上でOS上にプリンタを登録します。
install-printer.ps
# ---------- 設定 ---------------
# ドライバのパス 通常はinfファイルがあるフォルダ
$DriverPath="ドライバフォルダへのパス"
# infファイルへのパス
$InfPath = "INFファイルへのフルパス.inf"
# ドライバ名
$DriverName="ドライバ名"
# IPアドレス
$IpAddress="IPアドレス"
# プリンタ名(任意)
$PrinterName="プリンタ名"
# プロトコル 1=raw 2=lpr
$Protocol = 1
# ポート 通常rawの場合9100 lprの場合は515
$PortNo = 9100
# ----------------------------------------------
# --- プリンタドライバインストール ----
$PrinterDriverClass=New-Object System.Management.ManagementClass("Win32_PrinterDriver")
$NewPrinterDriver=$PrinterDriverClass.CreateInstance()
$NewPrinterDriver.Name=$DriverName
$NewPrinterDriver.Version=3
$NewPrinterDriver.DriverPath=$DriverPath
$NewPrinterDriver.InfName=$InfPath
$PrinterDriverClass.AddPrinterDriver($NewPrinterDriver)
$PrinterDriverClass.Put()
# --- ポート設定 ---
# USBの場合は不要
$PrinterPortClass=New-Object System.Management.ManagementClass("Win32_TcpIpPrinterPort")
$NewPort=$PrinterPortClass.CreateInstance()
$NewPort.name=$IpAddress
$NewPort.Protocol=$Protocol
$NewPort.HostAddress=$IpAddress
$NewPort.PortNumber=$PortNo
$NewPort.SnmpEnabled=$true
$NewPort.Put()
# --- プリンタの生成 ---
$PrinterClass=New-Object System.Management.ManagementClass("Win32_Printer")
$NewPrinter=$PrinterClass.CreateInstance()
$NewPrinter.drivername=$DriverName
# USBプリンタの場合はポート名を後述のようにします
$NewPrinter.PortName=$IpAddress
$NewPrinter.DeviceID=$PrinterName
$NewPrinter.Put()
# 通常使うプリンタに
# $NewPrinter.SetDefaultPrinter()
USBプリンタを設定する場合は、USBの後の連番がいくつになるかが不定なのでスクリプトを組みづらいですが、Get-PrinterPortコマンドから、Descriptionの値を頼りにポート名を見つける方法が考えられます。そこで得られたポート名をPortNameプロパティにセットします。
PS > Get-PrinterPort | Where Name -match "USB"
Name ComputerName Description PortMonitor
---- ------------ ----------- -----------
USB002 CanonG7000 series Dynamic Print Mon...
# CanonG7000 seriesという値を決め打ちでポートを取得
$ports = Get-PrinterPort | Where-Object { $_.Name -Like "USB*" -and $_.Description -eq "CanonG7000 series" }
...
# プリンタを設定する時にポートを次のようにします
# $portsはnullになることがあるので注意してください
$printer.PortName=$ports[0].Name
参考にさせていただきましたサイトの皆様、ありがとうございました。