Sending Wake-on-LAN Magic Packets from C#

I present, with little introduction, the MACAddress class. Within you will find simple test and conversion methods, with a single, simple to use method for sending a WOL ‘Magic’ Packet.

 

// MACAddress Class (Sending WOL 'Magic' Packets)
// Written by John Storer II (Feb 20, 2012)
//
// Feel free to use/modify this code as you wish, without liability.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace SendWOLPacket
{
    public class MACAddress
    {
        /// <summary>
        /// Test a MACAddress byte Array.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static bool Test(byte[] macAddress) {
            if (macAddress == null) return false;
            if (macAddress.Length != 6) return false;

            return true;
        }

        /// <summary>
        /// Test a MACAddress string.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static bool Test(string macAddress) {
            var valid_chars = "0123456789ABCDEFabcdef";

            if (string.IsNullOrEmpty(macAddress)) return false;
            if (macAddress.Length != 12) return false;

            foreach (var c in macAddress) {
                if (valid_chars.IndexOf(c) < 0) {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Parse a MACAddress string into a byte array.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static byte[] Parse(string macAddress) {
            byte[] mac = new byte[6];

            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress string.",
                    "macAddress",
                    null);

            for (var i = 0; i < 6; i++) {
                var t = macAddress.Substring((i * 2), 2);
                mac[i] = Convert.ToByte(t, 16);
            }

            return mac;
        }

        /// <summary>
        /// Attempt to parse a MACAddress string
        ///   without throwing an Exception.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <param name="Address"></param>
        /// <returns></returns>
        public static bool TryParse(string macAddress, out byte[] Address) {
            try {
                Address = Parse(macAddress);
                return true;
            }
            catch {
                Address = null;
                return false;
            }
        }

        /// <summary>
        /// Convert a byte array MACAddress to a string.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static string ToString(byte[] macAddress) {
            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress byte array.",
                    "macAddress",
                    null);

            return BitConverter.ToString(macAddress).Replace("-", "");
        }


        /// <summary>
        /// Sends a Wake-On-LAN 'magic' packet to
        ///   the specified MACAddress string.
        /// </summary>
        /// <param name="macAddress"></param>
        public static void SendWOLPacket(string macAddress) {

            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress string.",
                    "macAddress",
                    null);
            
            byte[] mac = Parse(macAddress);

            SendWOLPacket(mac);
        }

        /// <summary>
        /// Sends a Wake-On-LAN 'magic' packet to
        ///   the specified MACAddress byte array.
        /// </summary>
        /// <param name="macAddress"></param>
        public static void SendWOLPacket(byte[] macAddress) {

            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress byte array.",
                    "macAddress",
                    null);

            // WOL 'magic' packet is sent over UDP.
            using (UdpClient client = new UdpClient()) {

                // Send to: 255.255.255.0:40000 over UDP.
                client.Connect(IPAddress.Broadcast, 40000);

                // Two parts to a 'magic' packet:
                //     First is 0xFFFFFFFFFFFF,
                //     Second is 16 * MACAddress.
                byte[] packet = new byte[17 * 6];

                // Set to: 0xFFFFFFFFFFFF.
                for (int i = 0; i < 6; i++) {
                    packet[i] = 0xFF;
                }

                // Set to: 16 * MACAddress
                for (int i = 1; i <= 16; i++) {
                    for (int j = 0; j < 6; j++) {
                        packet[i * 6 + j] = macAddress[j];
                    }
                }

                // Send WOL 'magic' packet.
                client.Send(packet, packet.Length);
            }
        }

    }
}

Using this code is as simple as (assuming you have a form, a button named bSend and a text box named tbMACAddress):

private void bSend_Click(object sender, EventArgs e) {
    try {
        MACAddress.SendWOLPacket(tbMACAddress.Text);

        MessageBox.Show(
            string.Format("Packet Sent to '{0}'", tbMACAddress.Text));
    }
    catch (Exception Error) {
        MessageBox.Show(
            string.Format("Error:\n\n{0}", Error.Message), "Error");
    }
            
}

Why write a class to send WOL Packets? Mainly because I needed to wake up a PC at home remotely, if I really needed it. Also, someone here at work said, “I need to send WOL to this laptop, but I don’t have the Altiris Console handy,” to which I replied:

Challenge Accepted

Because who doesn't like a good challenge?

Comments Off