如何在Win 10 UWP项目中找到本地IP地址

11

我目前正在尝试将一款管理控制台应用程序移植到Win 10 UWP应用程序。我遇到了使用以下控制台代码中的System.Net.Dns的问题。

我该如何获取设备的IP地址?

这是我正在尝试移植的控制台应用程序代码。

public static string GetIP4Address()
{
    string IP4Address = String.Empty;
    foreach (IPAddress IPA in Dns.GetHostAddresses(Dns.GetHostName()))
    {
        if (IPA.AddressFamily == AddressFamily.InterNetwork)
        {
            IP4Address = IPA.ToString();
            break;
        }
    }
    return IP4Address;
}
3个回答

14

使用此代码可以在UWP应用中获取主机IP地址,我已经测试过:

    foreach (HostName localHostName in NetworkInformation.GetHostNames())
    {
        if (localHostName.IPInformation != null)
        {
            if (localHostName.Type == HostNameType.Ipv4)
            {
                textblock.Text = localHostName.ToString();
                break;
            }
        }
    }

查看API文档,请点击这里


如果您安装了VirtualBox,那么以下代码将无法正常工作。在我的情况下,表达式NetworkInformation.GetHostNames().FirstOrDefault(name => name.Type == HostNameType.Ipv4)?.DisplayName ?? "???"返回的是VirtualBox设置的虚拟交换机的IP地址。 - George Birbilis
为了解释这个原理,文档中提到:“当HostName对象是由GetHostNames方法返回的本地IPv4或IPv6地址时,才会设置IPInformation属性。此属性表示本地IP地址的IPInformation对象。如果HostName对象不是本地IPv4或IPv6地址,则此属性将为空。” - dwb
我可以问一下,由于我有多个DCHP地址(用于Wi-Fi和以太网),我如何确保始终获取Wi-Fi地址?由于循环在第一个实例上中断,这是因为Wi-Fi地址总是第一个吗? - dwb

11

您可以尝试像这样:

private string GetLocalIp()
{
    var icp = NetworkInformation.GetInternetConnectionProfile();

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

    // the ip address
    return hostname?.CanonicalName;
}

上面的答案也是正确的


我很难决定使用其中哪一个,所以我会在一些实验之后回到答案检查标记。 - Daniel Jerome
看起来它们都能工作,但我标记了第二个,因为它在一个返回字符串的方法中,就像我的原始示例一样。它也更符合我编码偏好的“风格”。感谢大家,你们拯救了这一天。 - Daniel Jerome
这段代码确实返回本地IP地址,而“其他代码”返回设备或本地网络用于连接互联网的IP地址。 - JuanK
3
这会抛出一个LINQ异常——在我的情况下,序列包含多个匹配元素(正如我在其他评论中所写,我的适配器列表中还设置了VirtualBox的虚拟交换机)。我将其从SingleOrDefault更改为FirstOrDefault以避免这种情况,并返回了IPv6地址。请查看我的答案以获取获取IPv4地址的解决方法。 - George Birbilis
1
还有,@panda 提供的另一个答案可能会返回错误的答案(在我的情况下是由 VirtualBox 设置的虚拟交换机的地址)。 - George Birbilis

5

基于@John Zhang的答案,但修复了不抛出关于多个匹配项的LINQ错误并返回IPv4地址的问题:

   public static string GetFirstLocalIp(HostNameType hostNameType = HostNameType.Ipv4)
    {
        var icp = NetworkInformation.GetInternetConnectionProfile();

        if (icp?.NetworkAdapter == null) return null;
        var hostname =
            NetworkInformation.GetHostNames()
                .FirstOrDefault(
                    hn =>
                        hn.Type == hostNameType &&
                        hn.IPInformation?.NetworkAdapter != null && 
                        hn.IPInformation.NetworkAdapter.NetworkAdapterId == icp.NetworkAdapter.NetworkAdapterId);

        // the ip address
        return hostname?.CanonicalName;
    }

显然,你可以传递HostNameType.Ipv6代替默认的(隐式)参数值Ipv4来获取Ipv6地址。


注意:在LINQ查询中添加HostNameType检查后,它不再抛出有关多个匹配项的异常,但为了安全起见,我将SingleOrDefault更改为FirstOrDefault。 - George Birbilis
不知道为什么有人给这个回答点了踩,它是唯一一个纠正其他回答错误IP地址的。 - George Birbilis
1
这是最好的答案。不确定为什么会被踩,因为你的答案是大多数情况下要使用的最佳代码。此外,在这里使用FirstOrDefault也是最好的LINQ方法,因为一台机器上可能有多个IP地址IPV4或IPV6。调用函数GetFirstLocalIP(),一切都很好。 - David Glass
确实,重命名 - George Birbilis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接