如何在 IP 范围内找到 Windows 台 PC
How to find Windows PCs in an IP range
我想扫描网络并枚举所有 windows 机器的主机名。有一个接口方法将 ip 范围作为输入和 returns 主机名。我必须实施它。所以,这是我的代码:
public ICollection<string> EnumerateWindowsComputers(ICollection<string> ipList)
{
ICollection<string> hostNames = new List<string>();
foreach (var ip in ipList)
{
var hostName = GetHostName(ip);
if (string.IsNullOrEmpty(hostName) == false)
{
hostNames.Add(hostName)
}
}
return hostNames;
}
private static string GetHostName(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
if (entry != null)
{
return entry.HostName;
}
}
catch (SocketException ex)
{
System.Console.WriteLine(ex.Message + " - " + ipAddress);
}
return null;
}
此方法成功枚举了所有windows台机器,但其中有网络打印机。我可以很容易地忽略打印机的主机名,但这不是一个好的解决方案。我必须确保只返回具有 Windows 操作系统的设备。
知道如何在没有第三方库的情况下做到这一点吗?如果有更好的方法,我们就不用GetHostName
方法了。
P.S。 Linux、MacOS、Android 和 IOS 设备未按预期找到。
服务检测不会是真的,因为可能有 linux 或其他框模拟 Windows FileSharing
使用来自 Windows 机器的 systeminfo /s IPADDRESS
shell 命令可靠地获取远程 Windows OS 详细信息。您的代码将如下所示:
string IPADDRESS = "192.168.1.1";
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.startInfo.FileName = "cmd.exe";
p.startInfo.Arguments = "/C systeminfo /s IPADDRESS";
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
if(output.Contains("Microsoft Windows")) { Console.WriteLine("Windows OS"); }
您可以尝试在远程计算机中检测 OS 的一种方法是使用 ping。 Ping 每个 IP 地址并获取 TTL。这应该让您了解您正在处理的 OS。 table 与 OS 匹配的 TTL 可以在这里找到:http://www.kellyodonnell.com/content/determining-os-type-ping
根据@Jeroen van Langen 的 ,我将 GetHostName
方法更改为 GetWindowsHostName
。
private string GetWindowsHostName(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
if (entry != null)
{
try
{
using (TcpClient tcpClient = new TcpClient())
{
// 445 is default TCP SMB port
tcpClient.Connect(ipAddress, 445);
}
using (TcpClient tcpClient = new TcpClient())
{
// 139 is default TCP NetBIOS port.
tcpClient.Connect(ipAddress, 139);
}
return entry.HostName;
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
}
catch (SocketException ex)
{
System.Console.WriteLine(ex.Message + " - " + ipAddress);
}
return null;
}
可能会有误报,但这对我来说不太可能并且可以接受。
我想扫描网络并枚举所有 windows 机器的主机名。有一个接口方法将 ip 范围作为输入和 returns 主机名。我必须实施它。所以,这是我的代码:
public ICollection<string> EnumerateWindowsComputers(ICollection<string> ipList)
{
ICollection<string> hostNames = new List<string>();
foreach (var ip in ipList)
{
var hostName = GetHostName(ip);
if (string.IsNullOrEmpty(hostName) == false)
{
hostNames.Add(hostName)
}
}
return hostNames;
}
private static string GetHostName(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
if (entry != null)
{
return entry.HostName;
}
}
catch (SocketException ex)
{
System.Console.WriteLine(ex.Message + " - " + ipAddress);
}
return null;
}
此方法成功枚举了所有windows台机器,但其中有网络打印机。我可以很容易地忽略打印机的主机名,但这不是一个好的解决方案。我必须确保只返回具有 Windows 操作系统的设备。
知道如何在没有第三方库的情况下做到这一点吗?如果有更好的方法,我们就不用GetHostName
方法了。
P.S。 Linux、MacOS、Android 和 IOS 设备未按预期找到。
服务检测不会是真的,因为可能有 linux 或其他框模拟 Windows FileSharing
使用来自 Windows 机器的 systeminfo /s IPADDRESS
shell 命令可靠地获取远程 Windows OS 详细信息。您的代码将如下所示:
string IPADDRESS = "192.168.1.1";
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.startInfo.FileName = "cmd.exe";
p.startInfo.Arguments = "/C systeminfo /s IPADDRESS";
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
if(output.Contains("Microsoft Windows")) { Console.WriteLine("Windows OS"); }
您可以尝试在远程计算机中检测 OS 的一种方法是使用 ping。 Ping 每个 IP 地址并获取 TTL。这应该让您了解您正在处理的 OS。 table 与 OS 匹配的 TTL 可以在这里找到:http://www.kellyodonnell.com/content/determining-os-type-ping
根据@Jeroen van Langen 的 GetHostName
方法更改为 GetWindowsHostName
。
private string GetWindowsHostName(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
if (entry != null)
{
try
{
using (TcpClient tcpClient = new TcpClient())
{
// 445 is default TCP SMB port
tcpClient.Connect(ipAddress, 445);
}
using (TcpClient tcpClient = new TcpClient())
{
// 139 is default TCP NetBIOS port.
tcpClient.Connect(ipAddress, 139);
}
return entry.HostName;
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
}
catch (SocketException ex)
{
System.Console.WriteLine(ex.Message + " - " + ipAddress);
}
return null;
}
可能会有误报,但这对我来说不太可能并且可以接受。