如何在.NET中获取本地IP?

5
我有以下vbscript代码,可以返回本地IP地址。它工作得很好。我尝试在我的winform .net应用程序中提供相同的功能。
我找到的所有解决方案都涉及使用DNS。有没有什么方法可以将这个脚本“移植”到.net中使用?
也许有一种不同的方法来做到这一点?
谢谢!
Function GetIP()

 Dim ws : Set ws = CreateObject("WScript.Shell")
  Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
  Dim TmpFile : TmpFile = fso.GetSpecialFolder(2) & "/ip.txt"
  Dim ThisLine, IP
  If ws.Environment("SYSTEM")("OS") = "" Then
    ws.run "winipcfg /batch " & TmpFile, 0, True
  Else
    ws.run "%comspec% /c ipconfig > " & TmpFile, 0, True
  End If
  With fso.GetFile(TmpFile).OpenAsTextStream
    Do While NOT .AtEndOfStream
      ThisLine = .ReadLine
      If InStr(ThisLine, "Address") <> 0 Then IP = Mid(ThisLine, InStr(ThisLine, ":") + 2)
    Loop
    .Close
  End With

  If IP <> "" Then
    If Asc(Right(IP, 1)) = 13 Then IP = Left(IP, Len(IP) - 1)
  End If
  GetIP = IP
  fso.GetFile(TmpFile).Delete  
  Set fso = Nothing
  Set ws = Nothing
End Function
5个回答

9

你可以通过查询网络接口来实现这一点,但这将包括所有本地地址,因此如果有多个接口(很可能会有),你可能需要添加一个 where 子句来选择所需的接口。这肯定不是你脚本的直接端口,但希望对你有所帮助:

var localAddress = 
    (from ni in NetworkInterface.GetAllNetworkInterfaces()
     where ni.NetworkInterfaceType != NetworkInterfaceType.Loopback
     let props = ni.GetIPProperties()
     from ipAddress in props.UnicastAddresses
     select ipAddress).FirstOrDefault();    

注意:如果您只需要IPv4地址,则可以修改查询为:
var localAddress = 
    (from ni in NetworkInterface.GetAllNetworkInterfaces()
     where ni.NetworkInterfaceType != NetworkInterfaceType.Loopback
     let props = ni.GetIPProperties()
     from ipAddress in props.UnicastAddresses
     where ipAddress.AddressFamily == AddressFamily.InterNetwork // IPv4
     select ipAddress).FirstOrDefault();     

和我之前发表的评论一样的问题。它返回的是 --> fe80 :: ad11:2dc5:58af:a24b%14,我现在已经发现这是我的IPv6地址。 - Refracted Paladin
嗯,我打算接受这个作为答案,因为它实际上可以在任何没有IPv6的设备上返回正确的IPv4地址;而我的目标受众中没有人使用IPv6,所以这个方法可行。我很想弄清楚如何选择特定的条目,但是...唉! - Refracted Paladin
我添加了这个来使它工作 --> 当 ipAddress.Address.AddressFamily == AddressFamily.InterNetwork // IPv4 但是接着发生了一些奇怪的事情。它报告了一个我不认识的IP地址... - Refracted Paladin
从GetAllNetworkInterfaces获得的输出应该对应于在命令提示符下键入“ipconfig / all”的输出。网络接口具有名称和其他属性,您可以使用这些属性来识别它们,因此,如果删除对FirstOrDefault的调用,则可以枚举序列并列出所有网络接口。 - Greg Beech
你可能还需要在第一个 where 子句上加上 ni.OperationalStatus == OperationalStatus.Up,否则你可能会得到一个当前不可用的适配器的 IP。我在一台带有无线和有线适配器的笔记本电脑上发现了这个问题;当关闭无线适配器时,我仍然能够获取到它的 IP。 - Keith Robertson

5
using System.Net;

IPAddress localAddr = Dns.GetHostEntry(Dns.GetHostName().ToString()).AddressList[0];

[编辑] 嗯......刚意识到你提到你不想使用DNS......为什么呢?

[编辑] 从评论中移动上来....

如果您只关心本地,那么将空字符串传递给GetHostEntry将默认返回本地。

IPAddress localAddr = Dns.GetHostEntry("").AddressList[0];

感谢您抽出时间发帖!DNS 要求他们目前必须能够访问我们的 DNS,对吗?除非这种说法是不正确的,否则我的问题在于我的应用程序是一种有时连接的应用程序,它不会始终连接到我们的家庭网络。他们可能在自己的家中或客户的家中。另外,我觉得很有趣的是,您的回答与我发布的内容相反,却获得了 4 个赞同。我并不是有意冒犯,只是我越来越多地注意到这一点。再次感谢! - Refracted Paladin
这个返回值为 fe80::ad11:2dc5:58af:a24b%14,你有什么想法吗? - Refracted Paladin
3
请注意,自从XP(甚至可能追溯到2000年)起,所有Windows系统都包含内置的DNS服务。即使您没有连接到任何网络,使用DNS查找计算机的主机条目仍应该可以工作。我认为这是目前最好的答案......它简单明了,并且在客户家中也能完成工作。 - jrista
嗯,这种方法的唯一问题是你必须预测你将需要哪个index[]。如果你选对了,它会非常好用。 - Refracted Paladin
2
您永远不会有一个空的地址列表,它会首先抛出异常......更简单的版本是IPAddress localAddr = Dns.GetHostEntry(“”)。AddressList [0];如果在GetHostEntry中放入一个空字符串,默认情况下它将返回本地IP。 - curtisk
显示剩余4条评论

2

看起来你的脚本正在调用ipconfig命令,将输出保存到文件中,然后解析文件。如果你想这样做,可以像这样操作:

using System.Threading;

...

static void Main(string[] args)
{
    Process p = new Process();

    ProcessStartInfo psi = new ProcessStartInfo("ipconfig");
    psi.CreateNoWindow = true;
    psi.RedirectStandardOutput = true;
    psi.UseShellExecute = false;

    p.StartInfo = psi;
    p.Start();

    string s = p.StandardOutput.ReadToEnd();
    int startPos = s.IndexOf(":", s.IndexOf("IPv4 Address"));
    string output = s.Substring(startPos + 2, s.IndexOf("\r\n", startPos) - startPos - 2);
    Console.WriteLine(output);
    Console.ReadLine();
}

注意,我并不特别喜欢这种方法——你可能会更好地使用本主题中列出的其他解决方案之一——但它是对你原始脚本更直接的翻译。


1

我个人建议使用 DNS,但如果您绝对不想使用,可以通过调用 System.Management 命名空间获取信息。

string ipAddress = "";
ManagementObjectSearcher query =
    new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'");
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject mo in queryCollection)
{
    string[] addresses = (string[]) mo["IPAddress"];
    if (addresses.Length == 1 && addresses[0] != "0.0.0.0")
    {
        ipAddress = addresses[0];
        break;
    }

}
Console.WriteLine(ipAddress);

这应该可以正确获取IP,但可能需要一些微调。


我可能太蠢了,但是在我的System.Management命名空间中似乎不存在ManagementObjectSearcher???.net 35 sp1 - Refracted Paladin
@Refracted Paladin:你是否已经将System.Management程序集添加到项目的引用中了? - Helen

0

您可以滚动此处以查找所有IP地址。

    String hostName = Dns.GetHostName();                      
    IPHostEntry local = Dns.GetHostByName(hostName);
    foreach (IPAddress ipaddress in local.AddressList)
    {
        ipaddress.ToString();  //this gives you the IP address
        //logic here 
    }

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