WSD接続のプリンタのIPアドレスを取得する方法

投稿者: | 2022年7月5日

ネットワーク接続のプリンタについて、プリンタの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

もう少し簡単に取得させてもらえないものだろうか・・・。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です