Programmatically Wake Up On Lan using .net

I’ve been meaning to write a web site to list a number of machines and allow the user to issue a Wake Up On Lan command to them. Looking around the web I found a great VB sample to issue the command. However, I didn’t want to pollute my nice c# with yukky VB  so converted it to c# and changed a few bits to bring it align with Microsoft standards.
 

using

System;

using

System.Collections.Generic;

using

System.Text;

using System.Net;

using

System.Net.Sockets;

using

System.Globalization;

 

namespace

Utilities.Network

{

/// <summary>

/// Utility class to wake machines up that are configured to "Wake Up On Lan"

/// </summary>

/// <remarks>Code orginally written in VB from http://www.lucamauri.com/snippet/snip.aspx?id=6</remarks>

public sealed class WakeUpOnLan

{

/// <summary>

/// Initialise using the default values

/// </summary>

/// <remarks>The default IPEndPoint transmit on port 7. Other choices for WOL are port 0 or 9</remarks>

public WakeUpOnLan()

{

this.endPoint = new IPEndPoint(IPAddress.Broadcast, 7);

}

/// <summary>

/// Initialise using a specific port

/// </summary>

/// <param name="port">A valid port number</param>

/// <remarks>If the port number is invalid, the IPEndPoint is created to port 7. Ports normally used for WOL are 0, 7 or 9.</remarks>

public WakeUpOnLan(int port)

{

if (port >= 0 && port < 65535)

{

endPoint =

new IPEndPoint(IPAddress.Broadcast, port);

}

else

{

endPoint =

new IPEndPoint(IPAddress.Broadcast, 7);

}

}

 

/// <summary>

/// The IPEndPoint object that will act as a trasport for the packet.

/// It is automatically created by New statement, but you can modify it or read it.

/// </summary>

/// <value>An IPEndPoint object</value>

/// <returns>An IPEndPoint object</returns>

/// <remarks>Normally there is no need to change this manually.</remarks>

public IPEndPoint EndPoint

{

get

{

return this.endPoint;

}

set

{

this.endPoint = value;

}

}

/// <summary>

/// The target machine Network Interface Card MAC address.

/// It must be dash-separated, i.e. in the 11-22-33-44-55-66 form

/// </summary>

/// <value>A string with dash-separated values</value>

/// <returns>A string with dash-separated values</returns>

/// <remarks>The standard (IEEE 802) separator for cotet are dash (-) and semicolon (:). I resolved to use dashes only in order to avoid any possible confusion and misunderstanding with upcoming IPv6 addressing space.</remarks>

public string MacAddress

{

get

{

StringBuilder textMAC = new StringBuilder();

foreach (byte currByte in this.macAddress)

{

textMAC.Append(

"-");

textMAC.Append(currByte.ToString(

"X2"));

}

return textMAC.ToString().Substring(1);

}

set

{

if (String.IsNullOrEmpty(value))

{

throw new FormatException(MacFormatMessage);

}

Queue<byte> values = new Queue<byte>();

string[] hexValues = value.Split(‘-‘);

if (hexValues.Length != 6)

{

throw new FormatException(MacFormatMessage);

}

foreach (string currByte in hexValues)

{

byte convertedByte;

if (Byte.TryParse(currByte, System.Globalization.NumberStyles.HexNumber,

CultureInfo.InvariantCulture, out convertedByte))

{

values.Enqueue(convertedByte);

}

else

{

throw new FormatException(MacFormatMessage);

}

}

this.macAddress = values.ToArray();

}

}

/// <summary>

/// Total bytes sent by WakeIt method. It is 0 until the method is called at least once for this class instance.

/// </summary>

/// <returns>Integer value, total bytes trasmitted</returns>

/// <remarks></remarks>

public int BytesSent

{

get

{

return this.bytesSent;

}

}

/// <summary>

/// It represent the Magic Packet broadcasted.

/// </summary>

/// <returns>String containing the text parsing of the Magic Packet</returns>

/// <remarks></remarks>

public string PacketSent

{

get

{

return packetSent;

}

}

/// <summary>

/// Creates a WOL Magic Packet, the datagram that will awake the target PC upon broadcast on the network.

/// </summary>

/// <param name="macAddress">An array of byte representing the target machine Network Interface Card MAC address</param>

/// <returns>An array of byte representing the Magic Packet</returns>

/// <remarks>This method can be used indipendently from the rest of the class. If necessary it can create a Magic Packet just providing the MAC address.</remarks>

private byte[] MagicPacket(byte[] macAddress)

{

if (macAddress.Length == 0)

{

throw new FormatException("Invalid MAC address");

}

byte[] payloadData = new byte[0];

StringBuilder packet = new StringBuilder();

 

payloadData =

new byte[HeaderLength + MacLength * repMAC];

for (int i = 0; i < HeaderLength; i++)

{

payloadData[i] =

Byte.Parse("FF", System.Globalization.NumberStyles.HexNumber);

}

for (int i = 0; i < repMAC; i++)

{

for (int j = 0; j < MacLength; j++)

{

payloadData[HeaderLength + i * MacLength + j] = macAddress[j];

}

}

foreach (byte currLoad in payloadData)

{

packet.Append(

"-");

packet.Append(currLoad.ToString("X2"));

}

packetSent = packet.ToString().Substring(1);

 

return payloadData;

}

private int SendUdp(byte[] payload, IPEndPoint endPoint)

{

int byteSend;

if ((payload != null) && (endPoint != null))

{

Socket socketClient = new Socket(endPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

socketClient.Connect(endPoint);

byteSend = socketClient.Send(payload, 0, payload.Length,

SocketFlags.None);

socketClient.Close();

}

else

{

byteSend = 0;

}

return byteSend;

}

/// <summary>

/// It is the main method of the class. It must be called after the MAC address has been set. It does not return any code, you can see the result of the operation with the bytesSent and packetSent properties of this class.

/// </summary>

/// <remarks></remarks>

public void WakeIt()

{

bytesSent = SendUdp(MagicPacket(macAddress), endPoint);

}

const int HeaderLength = 6;

const int MacLength = 6;

const int repMAC = 16;

const string MacFormatMessage = "Mac Format should be; XX-XX-XX-XX-XX, e.g. 00-13-71-BC-C2-CE";

IPEndPoint endPoint;

byte[] macAddress;

int bytesSent = 0;

string packetSent;

}

}

One thought on “Programmatically Wake Up On Lan using .net

  1. Mario August 2, 2008 / 12:37 pm

    Thanks, very useful 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s