很老的问题,我知道,但仍然有效。由于在接受的答案中没有看到任何 C#,我编写了自己的“Wake On Lan”代码。
我的目标是制作一个通用且简单Wake On Lan class
的:
- 适用于ipv4、ipv6和dual-stack。
- 适用于连接到不同网络(两台计算机)的一个或多个网卡(NICS)。
- 可与任何标准十六进制格式的macaddress一起使用。
- 使用多播工作(使用多个 NIC 时,Windows 中的广播有问题,使用 ipv6 时不支持)。
如何使用:
您所需要的只是您要唤醒的计算机上有线网卡的MAC地址。任何标准的十六进制表示都可以。然后像这样调用代码:
string mac = "01-02-03-04-05-06";
await WOL.WakeOnLan(mac);
这是课程:
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
public static class WOL
{
public static async Task WakeOnLan(string macAddress)
{
byte[] magicPacket = BuildMagicPacket(macAddress);
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where((n) =>
n.NetworkInterfaceType != NetworkInterfaceType.Loopback && n.OperationalStatus == OperationalStatus.Up))
{
IPInterfaceProperties iPInterfaceProperties = networkInterface.GetIPProperties();
foreach (MulticastIPAddressInformation multicastIPAddressInformation in iPInterfaceProperties.MulticastAddresses)
{
IPAddress multicastIpAddress = multicastIPAddressInformation.Address;
if (multicastIpAddress.ToString().StartsWith("ff02::1%", StringComparison.OrdinalIgnoreCase)) // Ipv6: All hosts on LAN (with zone index)
{
UnicastIPAddressInformation unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetworkV6 && !u.Address.IsIPv6LinkLocal).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
break;
}
}
else if (multicastIpAddress.ToString().Equals("224.0.0.1")) // Ipv4: All hosts on LAN
{
UnicastIPAddressInformation unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetwork && !iPInterfaceProperties.GetIPv4Properties().IsAutomaticPrivateAddressingActive).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
break;
}
}
}
}
}
static byte[] BuildMagicPacket(string macAddress) // MacAddress in any standard HEX format
{
macAddress = Regex.Replace(macAddress, "[: -]", "");
byte[] macBytes = new byte[6];
for (int i = 0; i < 6; i++)
{
macBytes[i] = Convert.ToByte(macAddress.Substring(i * 2, 2), 16);
}
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter bw = new BinaryWriter(ms))
{
for (int i = 0; i < 6; i++) //First 6 times 0xff
{
bw.Write((byte)0xff);
}
for (int i = 0; i < 16; i++) // then 16 times MacAddress
{
bw.Write(macBytes);
}
}
return ms.ToArray(); // 102 bytes magic packet
}
}
static async Task SendWakeOnLan(IPAddress localIpAddress, IPAddress multicastIpAddress, byte[] magicPacket)
{
using (UdpClient client = new UdpClient(new IPEndPoint(localIpAddress, 0)))
{
await client.SendAsync(magicPacket, magicPacket.Length, multicastIpAddress.ToString(), 9);
}
}
}
这个怎么运作:
该代码通过枚举所有“启动”并连接到您的网络(通常只有一个)的网卡来工作。它将使用多播向所有连接的网络发送“魔术包”,该多播适用于 ipv4 和 ipv6(不用担心网络泛滥,它只有 102 个字节)。
要工作,您要唤醒的计算机必须具有有线连接(无线计算机无法唤醒,因为它们未连接到任何网络,当它们关闭时)。发送数据包的计算机可以无线连接。
防火墙通常没有问题,因为计算机已关闭,因此防火墙未激活。
您必须确保它'Wake on lan'
在enabled
计算机BIOS
和网卡上。
.Net 6 的更新(和错误修复):
修复了一个错误,如果 Ipv6 在发送数据包的计算机上运行,但在应该被唤醒的计算机上没有,则它不会尝试 Ipv4(这在上面的代码中已修复)。
这是适用于 .Net 6 的代码(借用了@Oskar Sjôberg 的一些代码) - implicit usings turned on
:
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.RegularExpressions;
public static class WOL
{
public static async Task WakeOnLan(string macAddress)
{
byte[] magicPacket = BuildMagicPacket(macAddress);
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where((n) =>
n.NetworkInterfaceType != NetworkInterfaceType.Loopback && n.OperationalStatus == OperationalStatus.Up))
{
IPInterfaceProperties iPInterfaceProperties = networkInterface.GetIPProperties();
foreach (MulticastIPAddressInformation multicastIPAddressInformation in iPInterfaceProperties.MulticastAddresses)
{
IPAddress multicastIpAddress = multicastIPAddressInformation.Address;
if (multicastIpAddress.ToString().StartsWith("ff02::1%", StringComparison.OrdinalIgnoreCase)) // Ipv6: All hosts on LAN (with zone index)
{
UnicastIPAddressInformation? unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetworkV6 && !u.Address.IsIPv6LinkLocal).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
}
}
else if (multicastIpAddress.ToString().Equals("224.0.0.1")) // Ipv4: All hosts on LAN
{
UnicastIPAddressInformation? unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetwork && !iPInterfaceProperties.GetIPv4Properties().IsAutomaticPrivateAddressingActive).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
}
}
}
}
}
static byte[] BuildMagicPacket(string macAddress) // MacAddress in any standard HEX format
{
macAddress = Regex.Replace(macAddress, "[: -]", "");
byte[] macBytes = Convert.FromHexString(macAddress);
IEnumerable<byte> header = Enumerable.Repeat((byte)0xff, 6); //First 6 times 0xff
IEnumerable<byte> data = Enumerable.Repeat(macBytes, 16).SelectMany(m => m); // then 16 times MacAddress
return header.Concat(data).ToArray();
}
static async Task SendWakeOnLan(IPAddress localIpAddress, IPAddress multicastIpAddress, byte[] magicPacket)
{
using UdpClient client = new(new IPEndPoint(localIpAddress, 0));
await client.SendAsync(magicPacket, magicPacket.Length, new IPEndPoint(multicastIpAddress, 9));
}
}