31

Windows 8 WinRT/Metroアプリから実際のローカル IP アドレス (つまり、ループバック アドレスではない) を知る必要があります。これが必要な理由はいくつかあります。最も簡単なのは、アプリの UI に「ローカル ネットワークの IP アドレスは次のとおりです: [コードからクエリされた IP]」のようなテキストを表示したいというものです。

このアドレスは、追加のネットワーク通信にも使用されます。これらの通信は完全に有効です。なぜなら、コントロール パネルで IP アドレスを確認し、それをアプリにハードコードするとすべて機能するからです。ダイアログでユーザーに住所を見て手動で入力するように求めることは、私が本当に避けたいことです。

プログラムでアドレスを取得するのは複雑な作業ではないと思いますが、私の検索エンジンと StackOverflow のスキルは空っぽです。

この時点で、UDP ブロードキャスト/リッスン ループを実行して自分の要求を聞き、そこからアドレスを抽出することを検討し始めていますが、それは本当にハッキーなクラッジのようです。新しい WinRT のどこかに、そこに到達するための API はありますか?

「WinRT アプリ」と言ったことに注意してください。これは、Dns.GetHostEntryまたはのような一般的なメカニズムNetworkInterface.GetAllInterfaces()が機能しないことを意味します。

4

2 に答える 2

35

掘り下げた後、 NetworkInformationHostNameを使用して必要な情報を見つけました。

NetworkInformation.GetInternetConnectionProfileは、ローカル マシンで現在使用されているインターネット接続に関連付けられている接続プロファイルを取得します。

NetworkInformation.GetHostNamesは、ホスト名のリストを取得します。明らかではありませんが、これには IPv4 および IPv6 アドレスが文字列として含まれます。

この情報を使用して、インターネットに接続されているネットワーク アダプターの IP アドレスを次のように取得できます。

public string CurrentIPAddress()
{
    var icp = NetworkInformation.GetInternetConnectionProfile();

    if (icp != null && icp.NetworkAdapter != null)
    {
        var hostname =
            NetworkInformation.GetHostNames()
                .SingleOrDefault(
                    hn =>
                    hn.IPInformation != null && hn.IPInformation.NetworkAdapter != null
                    && hn.IPInformation.NetworkAdapter.NetworkAdapterId
                    == icp.NetworkAdapter.NetworkAdapterId);

        if (hostname != null)
        {
            // the ip address
            return hostname.CanonicalName;
        }
    }

    return string.Empty;
}

HostNameにはプロパティ CanonicalName、DisplayName、および RawName がありますが、それらはすべて同じ文字列を返すように見えることに注意してください。

次のようなコードを使用して、複数のアダプターのアドレスを取得することもできます。

private IEnumerable<string> GetCurrentIpAddresses()
{
    var profiles = NetworkInformation.GetConnectionProfiles().ToList();

    // the Internet connection profile doesn't seem to be in the above list
    profiles.Add(NetworkInformation.GetInternetConnectionProfile());

    IEnumerable<HostName> hostnames =
        NetworkInformation.GetHostNames().Where(h => 
            h.IPInformation != null &&
            h.IPInformation.NetworkAdapter != null).ToList();

    return (from h in hostnames
            from p in profiles
            where h.IPInformation.NetworkAdapter.NetworkAdapterId ==
                  p.NetworkAdapter.NetworkAdapterId
            select string.Format("{0}, {1}", p.ProfileName, h.CanonicalName)).ToList();
}
于 2012-05-04T22:12:25.233 に答える