Wake on LAN using C#
Asked Answered
L

3

15

What's the best way going forward to implement Wake on LAN using C#?

The functionality is needed for machines in a LAN environment (and not over the internet). The method needs to be robust enough to take care of firewalls and other such issues. Also, for systems not supporting this functionality, or having it disabled, is there an alternative?

The primary objective - wake up machines (from shutdown/hibernate state) over the LAN - this is to be programmed using C#.

Please guide.

PS: I've come across the following:

  1. http://blog.memos.cz/index.php/team/2008/06/12/wake-on-lan-in-csharp
  2. http://community.bartdesmet.net/blogs/bart/archive/2006/04/02/3858.aspx
  3. http://www.codeproject.com/KB/IP/cswol.aspx

However, I'm new to this and hence couldn't figure if the solutions were comprehensive enough. If someone could recommend following either of the above articles, that'd help.

Lingerfelt answered 14/5, 2009 at 6:42 Comment(1)
"The method needs to be robust enough to take care of firewalls and other such issues." What does this mean? You want to write a program in C# that can go through any firewall and manage to wake up a machine behind that firewall? That's a big ask...Watermark
J
15

For the WOL problem you have to clarify three problems to get it to work:

  1. Send a WOL over the ethernet cable
  2. Configure your PC to listen for such a packet and wake up
  3. Make sure the packet will come from sender to receiver (firewall, gateways, etc.)

As you already found on the net there are existing several solutions for the first problem programmed in C# (and after skimming your links, I would start with the first one).

The second one is something you can only achieve by configuring your network adapter. Just open the device manager and take a look into the properties of your network adapter, if such an option exists and if you can enable it. This can't be programmed, due to the fact that every network adapter has another implementation of that function and how it can be enabled.

The third problem can't also be solved by C#. It is a pure network problem, where you have to configure your router, gateways, ids-systems, etc. to allow such a packet and let it flow from sender to receiver. Due to the fact, that a WOL packet is always a broadcast packet (dest-ip 255.255.255.255) it won't leave your local network and will always be dropped from router, gateways or any other bridge between to networks (e.g. vpns, etc.).

Last but not least, I will just remind you, that the first problem can be divided into some smaller packets but as far as I could see these problems are all capped by the links you provided.

Joaniejoann answered 14/5, 2009 at 7:27 Comment(0)
S
33

Very old question, I know, but still valid. Since I didn't see any C# in the accepted answer, I wrote my own 'Wake On Lan' code.

My goal was to make a universal and easy Wake On Lan class that:

  • works with ipv4, ipv6 and dual-stack.
  • works with one or multiple network cards (NICS) connected to different networks (both computers).
  • works with macaddress in any standard hex format.
  • works using multicast (broadcast is buggy in Windows when using multiple NICs and is not supported when using ipv6).

How to use:

All you need, is the MAC address of the wired nic on the computer you wish to wake up. Any standard hex representation will do. Then call the code like this:

string mac = "01-02-03-04-05-06";
await WOL.WakeOnLan(mac);

Here's the class:

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);
        }
    }
}

How it works:

The code works by enumerating all network cards that are 'up' and connected to your network (that's usually just one). It will send out the 'magic packet' to all your connected networks using multicast, which works with both ipv4 and ipv6 (don't worry about flooding your network, it's only 102 bytes).

To work, the computer, you want to wake up, must have a wired connection (wireless computers can't be woken up, since they aren't connected to any network, when they are off). The computer, that sends the packet, can be wireless connected.

Firewalls are usually no problem, since the computer is off and hence the firewall is not active.

You must make sure that 'Wake on lan' is enabled in the computer's BIOS and on the network card.

Update for .Net 6 (and a bug fix):

Fixed a bug, where if Ipv6 was functioning on the computer that sends the packet but not on the one, that should be awakened, then it would not try Ipv4 (this is fixed in the code above).

Here's the code that works on .Net 6 (borrowed some of @Oskar Sjôberg's code) - 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));
    }
}
Softboiled answered 21/9, 2019 at 18:30 Comment(5)
Since Windows 10, the Green Energy Feature of the network adapter needs to be disabled; and als the "Fast-Boot" of Win 10 have to be switched off. Otherwise WOL will not workTransmitter
@KargWare: Thanks for sharing that info.Softboiled
@PoulBak Thanks . Your code it helps me a loot.Equites
I'm using VS2022 I also installed .net framework updates, but still could not add namespace for Convert.FromHexString and getting not supported error on UnicastIPAddressInformation?Marcellus
@sairfan: For .Net Framework, you must use the first code, the second only works for .Net 6+Softboiled
J
15

For the WOL problem you have to clarify three problems to get it to work:

  1. Send a WOL over the ethernet cable
  2. Configure your PC to listen for such a packet and wake up
  3. Make sure the packet will come from sender to receiver (firewall, gateways, etc.)

As you already found on the net there are existing several solutions for the first problem programmed in C# (and after skimming your links, I would start with the first one).

The second one is something you can only achieve by configuring your network adapter. Just open the device manager and take a look into the properties of your network adapter, if such an option exists and if you can enable it. This can't be programmed, due to the fact that every network adapter has another implementation of that function and how it can be enabled.

The third problem can't also be solved by C#. It is a pure network problem, where you have to configure your router, gateways, ids-systems, etc. to allow such a packet and let it flow from sender to receiver. Due to the fact, that a WOL packet is always a broadcast packet (dest-ip 255.255.255.255) it won't leave your local network and will always be dropped from router, gateways or any other bridge between to networks (e.g. vpns, etc.).

Last but not least, I will just remind you, that the first problem can be divided into some smaller packets but as far as I could see these problems are all capped by the links you provided.

Joaniejoann answered 14/5, 2009 at 7:27 Comment(0)
B
11

I was trying Poul Bak´s answer but was unable to wake my target computer. After verifying that a third party application, WakeMeOnLan in fact was able to wake my target computer, I wrote this code that worked for me:

void SendWakeOnLan(PhysicalAddress target)
{   
    var header = Enumerable.Repeat(byte.MaxValue, 6);
    var data = Enumerable.Repeat(target.GetAddressBytes(), 16).SelectMany(mac => mac);

    var magicPacket = header.Concat(data).ToArray();
    
    using var client = new UdpClient();

    client.Send(magicPacket, magicPacket.Length, new IPEndPoint(IPAddress.Broadcast, 9));
}

Usage:

Simply by passing in the target computers mac address like so:

SendWakeOnLan(PhysicalAddress.Parse("0A-0B-0C-0D-0E-0F"));

I think the main difference between this answer and Poul Bak´s answer is that this code is using broadcast over IPv4 instead of multicast on IPv4/IPv6, and maybe my network equipment is not handling/setup to do multicast correctly.

Basic answered 1/1, 2021 at 12:48 Comment(2)
I agree with your conclusion. Have you tried looking at your network card's Advanced properties? Some (old?) cards have multicast disabled.Softboiled
Actually I debugged the code to see what is going on. It is indeed sent to the correct multicast group. It might be my dumb switch, but more likely it is the appliance in my case that is coded to only read WOL-packets sent to the broadcast address.Isothere

© 2022 - 2024 — McMap. All rights reserved.