ネットワーク接続のプリンタについて、プリンタのIPアドレスを知りたいな、と思った時。
標準TCP/IPなプリンタならポートを見ればIPが分かるものの、WSDとかいうやつだとGUIのどこを見てもIPアドレスが判明せず、どれがどれやら・・・。
ということで、WSD接続のプリンタのIPアドレスを取得する方法を探してみたら、とある質問サイトでは「ない」と断言・・・。これは困る。というか、取れないって何だろう・・・。
結局レジストリを直接見に行けば何とか取れたっぽい。
プリンタ自体は、PowerShellで、Get-Printer
を実行すれば取得が出来る。ただし、そこにはポートの名前だけで、ポート情報はないので、別途Get-PrinterPortを実行して取得する。
$printers = Get-Printer
$printers | % {
$p=$_;
Get-PrinterPort -Name $p.PortName |
Select @{Name="PrinterName"; Expression={$p.Name}},
@{Name="PortName"; Expression={$_.Name}},
PrinterHostAddress, Description, PortMonitor
} | fl
こんな感じで取得できるはず。
PrinterName : Microsoft Print to PDF
PortName : PORTPROMPT:
PrinterHostAddress :
Description : ローカル ポート
PortMonitor : Local Monitor
PrinterName : プリンター1
PortName : 192.168.0.10
PrinterHostAddress : 192.168.0.10
Description : 標準の TCP/IP ポート
PortMonitor : TCPMON.DLL
PrinterName : プリンター2
PortName : WSD-12345678-9abc-def1-2345-6789abcdef01
PrinterHostAddress :
Description : WSD Port
PortMonitor : WSD Port Monitor
プリンター1は、PortNameがIPAddressになっているけれど、標準のTCP/IPポートで作った時の名前のほうが表示されているので、見るべきはPrinterHostAddressのほう。こちらはこれで完了。
問題はプリンター2のほうで、WSDの場合 PrinterHostAddressが入っていない。
でどうするかというと、PortMonitorがWSD Port Monitorの場合、
DeviceURL、DeviceUUIDという項目が記録されている。
DeviceURLが入っている場合、「http://192.168.0.11/StableWSDiscoveryEndpoint/schemas-xmlsoap-org_ws_2005_04_discovery」とかなんとか担っている。このURLのホスト名がIPアドレスとして使える。System.Uriを介してホスト部分だけ取り出せばOK。
([System.Uri]$_.DeviceURL).Host
ただ、ここが空白の場合がある。その場合は代わりにDeviceUUIDが入っている(ハズ)。
これを素にレジストリから取得する。以下に情報があった。
HKLM\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\ にDeviceUUIDのキーがあり、その中にあるLocationInformationを参照すれば、「http://192.168.0.11/WSD/DEVICE」みたいな感じではいっている。あとは上と同じでHostの部分を取り出せばOK
ということで、こんな感じになった。
# this hostname ( for shared printer name )
$hostNameFQDN = [System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).Hostname;
$hostName = hostname;
# Means of acquiring each type
$portMonitor = @{
"WSD Port Monitor" = @{
type = "WSD";
fnc = {
param ($pport);
if( ![string]::IsNullOrEmpty($pport.DeviceURL) ){
([System.Uri]$pport.DeviceURL).Host;
}elseif( ![string]::IsNullOrEmpty($pport.DeviceUUID) ){
$path = "hklm:\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\{0}" -f $pport.DeviceUUID;
((Get-ItemProperty $path -Name LocationInformation).LocationInformation | %{[System.Uri]$_}).Host
}
}
};
"TCPMON.DLL" = @{
type = "TCP/IP";
fnc = {
param ($pport);
$pport.PrinterHostAddress
}
};
};
# main routine (shared printer only)
$printers = @(Get-Printer | ? Shared | %{
# result object
$printer = [PsCustomObject]@{
Name = $_.Name;
Comment = $_.Comment;
PortType = "";
PortName = $_.PortName;
IPAddress = "";
ShareName = "";
ManageHost = $hostNameFQDN;
};
# Printer port
$pt = Get-PrinterPort -Name $_.PortName;
# Shared printer name nuild
if($_.Shared){ $printer.ShareName = "\\{0}\{1}" -f $hostName,$_.ShareName; }
# Get IP address by port monitor
if ( $portMonitor.ContainsKey($pt.PortMonitor) ){
$printer.PortType = $portMonitor[$pt.PortMonitor].type;
$printer.IPAddress = &$portMonitor[$pt.PortMonitor].fnc $pt;
}
$printer;
} | ? IPAddress);
# printer not found
if ( $printers.length -eq 0 ){ return; }
# output
$printers | fl
もう少し簡単に取得させてもらえないものだろうか・・・。