読者です 読者をやめる 読者になる 読者になる

tmori3y2のブログ

主にWindowsのプログラムなど

Hyper-Vの仮想スイッチで外部ネットワークとブリッジを構成しているとEpson Networkプリンタのセットアップが上手くいかない件1

Hyper-V Windows Desktop開発

FAX/コピー/プリンタ複合機の買い替え

FAX/コピー/プリンタ複合機であるHP Photosmart 2570 All-in-One Printerを長らく使用してきたが、以下の理由でEpson複合機に買い替えた。

  • Windows 10のユーティリティ・ドライバがなかった

  • インクカートリッジの持ちが悪かった

  • インクカートリッジが高かった

  • 近所にインクカートリッジのリサイクルボックスがなかった

代わりに選んだのがエプソン複合機EW-M660FT。

インクタンクでインクを補充するタイプだ。

www.epson.jp

もうちょっと安いのが欲しかったが、店に在庫があるので良いのがなかった。

Windws 10のセットアップが上手くいかない

ドライバとユーティリティのセットアップを実行すると、プリンタが見つからない。

無線LANか有線LANを指定してセットアップを行うのだが、Dell Inspiron 13は有線LANがないので、無線LANを選んでセットアップできないとお手上げ状態。

Windows 10の標準セットアップ

ところが、Windows 10の設定画面でプリンタとスキャナーの追加をすると一応プリンタだけはセットアップは出来る。

ただし、Epson標準の設定にならないので、複合機のすべての機能を使用することは出来ないのだが・・・

しかし、OSの標準機能で、セットアップできるということは、Epsonのセットアップに何か問題があるということだ。

ネットワークアダプタ構成

f:id:tmori3y2:20170116210620p:plain

ネットワークアダプタを表示してみるとピンときた。

Wi-Fiアダプタがブリッジになって、仮想アダプタでIPアドレスを設定するように変更されている。

これは、今に始まったことではなくて、少なくともXP時代からこんな仕様になっていたと思うが、おそらくこれで無線LANアダプタが探せなくなったのだろう。

試しに、コマンドプロンプトで以下を打ち込むと、やはり仮想アダプタのみ有効になっている。

ipconfig

Windows IP 構成


Wireless LAN adapter ローカル エリア接続* 2:

   メディアの状態. . . . . . . . . . . .: メディアは接続されていません
   接続固有の DNS サフィックス . . . . .: 

イーサネット アダプター vEthernet (WirelessVLAN):

   接続固有の DNS サフィックス . . . . .: 
   リンクローカル IPv6 アドレス. . . . .: fe80::3c11:6bb2:407d:a5e0%29
   IPv4 アドレス . . . . . . . . . . . .: 192.168.1.26
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: 192.168.1.1

イーサネット アダプター Bluetooth ネットワーク接続:

   メディアの状態. . . . . . . . . . . .: メディアは接続されていません
   接続固有の DNS サフィックス . . . . .: 

Tunnel adapter isatap.{5114AA4B-CCE8-482E-AF6D-CE9D876B70EB}:

   メディアの状態. . . . . . . . . . . .: メディアは接続されていません
   接続固有の DNS サフィックス . . . . .: 

Tunnel adapter Teredo Tunneling Pseudo-Interface:

   接続固有の DNS サフィックス . . . . .: 
   IPv6 アドレス . . . . . . . . . . . .: 2001:0:9d38:6ab8:1cb0:1ae6:f1f5:7abf
   リンクローカル IPv6 アドレス. . . . .: fe80::1cb0:1ae6:f1f5:7abf%21
   デフォルト ゲートウェイ . . . . . . .: ::

ここで、「Wireless LAN adapter ローカル エリア接続* 2」は、Microsoft Wi-Fi Direct Virtual Adapterで通常の無線LANアダプタではない、「イーサネット アダプター vEthernet (WirelessVLAN)」は仮想スイッチを外部アダプタとブリッジしたときに付けられた名前であることに注意してほしい。

ブリッジ構成の解除

さて、ネットワークアダプタの設定でブリッジを解除するのはHyper-Vが動かなくなりそうなので、出来ればやりたくないが、実はHyper-Vの仮想スイッチマネージャで簡単に切り替えられる。

f:id:tmori3y2:20161220073712p:plain

外部ネットワークに接続しているものを内部ネットワークに切り替えるだけ。

f:id:tmori3y2:20170116212252p:plain

実際、これでセットアップが上手くいった。

LinqPadで調査

LinqPadのDump()は、使い慣れていないクラスのコレクションなどを表示するのに重宝する。

そのため、今回もLinqPad+.NETでスクリプトを書いてみた。

System.Net.NetworkInformation.NetworkInterface

まずは、System.Net.NetworkInformation.NetworkInterface。

https://msdn.microsoft.com/ja-jp/library/system.net.networkinformation.networkinterface(v=vs.110).aspx

<Query Kind="Program">
  <Namespace>System.Net.NetworkInformation</Namespace>
</Query>

void Main()
{
    var WiFiAdapter = "Intel(R) Dual Band Wireless-AC 3165";    // Your Wireless Adapter is here.
    var vEthernet = "Hyper-V Virtual Ethernet Adapter";         // Hyper-V Virtual Switch.

    var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
    networkInterfaces.Dump();

    foreach (var networkInterface in networkInterfaces)
    {
        if (networkInterface.Description != WiFiAdapter && networkInterface.Description != vEthernet) continue;
        
        networkInterface.GetNetworkInterfaceProperties().Dump();
    }
}

public static class DisplayHelper
{
    public static IEnumerable<object> GetNetworkInterfaceProperties(this NetworkInterface networkInterface)
    {
        yield return networkInterface.Name;
        yield return networkInterface.Description;
        yield return networkInterface.NetworkInterfaceType;
        if (networkInterface.OperationalStatus == OperationalStatus.Up)
            yield return networkInterface.GetIPProperties()
                .UnicastAddresses.Select(x => x.Address.GetAddressBytes())
                .Where(x => x.Count() == 4)
                .Select(binary => string.Format("{0}.{1}.{2}.{3}", binary[0], binary[1], binary[2], binary[3]))
                .FirstOrDefault();
        yield return networkInterface.Id;
    }
}

ブリッジが構成されているときは、御覧の通り、アダプタ名"Wi-Fi"は見つからない。

f:id:tmori3y2:20170116213146p:plain

解除するともちろん認識されている。

f:id:tmori3y2:20170116213350p:plain

System.Management.ManagementObjectSearcher

次に、System.Management.ManagementObjectSearcherで、WMIのWin32_NetworkAdapter/MSNdis_PhysicalMediumType/Win32_NetworkAdapterConfigurationでアダプタを列挙する。

https://msdn.microsoft.com/en-us/library/windows/desktop/aa389273(v=vs.85).aspx#_hmm_networking_device_classes

<Query Kind="Program">
  <Reference>&lt;RuntimeDirectory&gt;\System.Management.dll</Reference>
  <Namespace>System.Management</Namespace>
</Query>

void Main()
{
    var WiFiAdapter = "Intel(R) Dual Band Wireless-AC 3165"; // Your Wireless Adapter is here.
    var vEthernet = "Hyper-V Virtual Ethernet Adapter";          // Hyper-V Virtual Switch.
    var Multiplexor = "Microsoft Network Adapter Multiplexor Driver";    // Network Bridge.

    var networkAdaptersQuery = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapter").Get()
        .Cast<ManagementObject>()
        .Where(x => (bool)x["PhysicalAdapter"]);
    //networkAdaptersQuery.Dump();

    var networkTypeQuery = new ManagementObjectSearcher(@"root\WMI", "SELECT * FROM MSNdis_PhysicalMediumType").Get()
        .Cast<ManagementObject>()
        .Select(x => x.Properties);
    //networkTypeQuery.Dump();

    var networkAdapterConfigurationsQuery = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration").Get()
        .Cast<ManagementObject>()
        .Select(x => x.Properties);
    //networkAdapterConfigurationsQuery.Dump();

    var networkAdapters =
        networkAdaptersQuery
        .Select(x => x.Properties);
        
    foreach (var networkAdapter in networkAdapters)
    {
        if ((string)networkAdapter["Description"].Value != WiFiAdapter &&
            (string)networkAdapter["Description"].Value != vEthernet &&
            (string)networkAdapter["Description"].Value != Multiplexor) continue;
        
        networkAdapter.GetNetworkAdapterProperties(networkTypeQuery, networkAdapterConfigurationsQuery).Dump();
    }

}

public static class DisplayHelper
{
    public static IEnumerable<object> GetNetworkAdapterProperties(this PropertyDataCollection networkAdapterProperties,
        IEnumerable<PropertyDataCollection> networkAdapterTypePropertiesList,
        IEnumerable<PropertyDataCollection> networkAdapterConfigurationPropertiesList)
    {
        var networkAdapterTypeProperties =
            networkAdapterTypePropertiesList
            .Where(x => (string)x["InstanceName"].Value == (string)networkAdapterProperties["Description"].Value)
            .FirstOrDefault();

        var networkAdapterConfigurationProperties =
            networkAdapterConfigurationPropertiesList
            .Where(x => (uint)x["Index"].Value == (uint)networkAdapterProperties["Index"].Value)
            .FirstOrDefault();

        yield return networkAdapterProperties["Description"].Value;
        yield return networkAdapterProperties["NetConnectionID"].Value;
        yield return networkAdapterProperties["GUID"].Value;
        yield return networkAdapterProperties["MACAddress"].Value;
        yield return networkAdapterProperties["AdapterType"].Value;
        yield return networkAdapterProperties["AdapterTypeId"].Value;
        yield return networkAdapterTypeProperties["NdisPhysicalMediumType"].Value;

        if ((bool)networkAdapterConfigurationProperties["IPEnabled"].Value)
        {
            var addressList = networkAdapterConfigurationProperties["IPAddress"].Value as string[];
            if (addressList != null && addressList.Count() > 0) yield return addressList[0];
        }

        //yield return networkAdapterProperties;
        //yield return networkAdapterTypeProperties;
        //yield return networkAdapterConfigurationProperties;
    }
}

Win32_NetworkAdapterのAdapterTypeIdが無線LAN(=9)でもBluetooth(=10)でも殆どのケースで、有線LAN(=0)になってしまう。

stackoverflow.com

を参考にMSNdis_PhysicalMediumTypeのNdisPhysicalMediumTypeを表示するようにした。

NdisPhysicalMediumTypeは、AdapterTypeIdと同様に9で無線LANを示すようである。

ブリッジ構成の結果は以下の通り。

f:id:tmori3y2:20170118005643p:plain

Wireless Adapter, Hyper-V Virtual Switch, Network BridgeのMAC AdressがすべてWireless Adapterのものになっており、IP AddressはHyper-V Virtual Switchにふられている。

この辺とMSNdis_PhysicalMediumTypeの結果を踏まえないと無線LANアダプタは見つからないだろう。

解除するともちろん認識されている。

f:id:tmori3y2:20170118010256p:plain

ただし、AdapterTypeIdが正しくないのは同じである。

ちなみに、MSNdis_PhysicalMediumTypeは、そのものずばりのリファレンスがなく調査中。

他にもMSNdis_があり、PowerShellの以下のコマンドで列挙できるようである。

Get-WmiObject -Namespace root\wmi -List | Where-Object {$.name -Match "MSNDis" }

次は、Native WiFi APIWindows RuntimeのWiFiAdapterで調べてみる。(つづく)

2017/01/18追記

WMIのMSNdis_PhysicalMediumTypeのドキュメントのありか

で質問してみたが、自己解決(?)

MSNdis_80211* classは使えそうかと思ったが、例外が出てしまう。残念・・・