I was looking for something to wake my remote machine on LAN or a different laptop connected in my network to wake up without having to press the power button again and again. There are some programs available but you have to pay for them. It's pretty easy to make a packet (so called magic packet) and broadcast it in the network. The packet contains the MAC address of the machine which has to be woken up. If that machine is in network and is connected via a LAN cable, it should wake itself up. So here is the program in C# which creates the magic packet and broadcasts it in the network. You might also like to check my post on Get MAC address from hostname or IP address to integrate this program and the other one together so you will just have to enter the hostname/IP address of the machine which you want woken up without worrying about it's MAC address. If you want just the exe, let me know via a comment here and I'll send you the executable. 1 // No copyrights(c). Use as you wish! 2 3 using System; 4 using System.Globalization; 5 using System.Text.RegularExpressions; 6 using System.Net; 7 using System.Net.Sockets; 8 9 namespace Yours.Truly 10 { 11 // ************************************************************************* 12 /// <summary> 13 /// A class to demonstrate Wake up on LAN. For this program to function, your 14 /// machine must be setup to accept wake-up on LAN requests. Usually this 15 /// option can set to "Enabled" state in boot(BIOS) options. You can see the 16 /// set value by Rebooting your PC/Laptop and press F2 just after you power 17 /// on your PC/Laptop. (you might have to keep pressing F2 until it comes up 18 /// with boot options) 19 /// </summary> 20 /// <remarks> 21 /// <para> 22 /// For more information see http://support.microsoft.com/kb/257277 and 23 /// http://en.wikipedia.org/wiki/Wake-on-LAN. 24 /// </para> 25 /// <para>For an in depth details please visit : 26 /// http://en.wikipedia.org/wiki/Data_link_layer and 27 /// http://en.wikipedia.org/wiki/Network_layer </para> 28 /// </remarks> 29 public sealed class WakeUpOnLan 30 { 31 // ********************************************************************* 32 /// <summary> 33 /// Main entry point of the application. 34 /// </summary> 35 /// <param name="args">An array of command line arguments.</param> 36 static void Main(string[] args) 37 { 38 bool wakeUp = true; 39 while (wakeUp) 40 { 41 Console.WriteLine("Enter the MAC address of the host to wake up " + 42 " on LAN (no space or hyphen(-). e.g. 0021702BA7A5." + 43 "Type Exit to end the program):"); 44 string macAddress = Console.ReadLine(); 45 46 StringComparer cp = StringComparer.OrdinalIgnoreCase; 47 if (cp.Compare(macAddress, "Exit") == 0) break; 48 49 //remove all non 0-9, A-F, a-f characters 50 macAddress = Regex.Replace(macAddress, @"[^0-9A-Fa-f]", ""); 51 //check if mac adress length is valid 52 if (macAddress.Length != 12) 53 { 54 Console.WriteLine("Invalid MAC address. Try again!"); 55 } 56 else 57 { 58 Wakeup(macAddress); 59 } 60 } 61 } 62 63 // ********************************************************************* 64 /// <summary> 65 /// Wakes up the machine with the given <paramref name="macAddress"/>. 66 /// </summary> 67 /// <remarks> 68 /// <para> 69 /// <note> 70 /// <list type="number"> 71 /// <item> The motherboard must support Wake On LAN.</item> 72 /// <item> The NIC must support Wake On LAN.</item> 73 /// <item> There must be a wire connecting the motherboard's WOL port to 74 /// the NIC's WOL port. Usually there always is a connection on most of 75 /// the PCs.</item> 76 /// <item> The Wake On LAN feature must be enabled in the motherboard's 77 /// BIOS. Usually this is also enabled by default, but you might like to 78 /// check again.</item> 79 /// <item> The "Good Connection" light on the back of the NIC must be lit 80 /// when the machine is off. (By default always good if you are not 81 /// facing any network issues)</item> 82 /// <item> Port 12287 (0x2FFF) must be open. (By default it should be 83 /// open unless some antivirus or any other such program has changed 84 /// settings.)</item> 85 /// <item> Packets cannot be broadcast across the Internet. That's why 86 /// it's called Wake On Lan, not Wake On Internet.</item> 87 /// <item> To find your MAC address, run the MSINFO32.EXE tool that is a 88 /// part of Windows and navigate to Components > Network > Adapteror 89 /// or simply type nbtstat -a <your hostname < at command prompt. 90 /// e.g. nbtstat -a mymachinename or nbtstat -A 10.2.100.213. 91 /// .</item> 92 /// </list> 93 /// </note> 94 /// </para> 95 /// <para>You could also use my other blog on "Get MAC address" to simply 96 /// integrate this program and my other program so you just have to input 97 /// the hostname/IP address of the machine which you want woken up.</para> 98 /// <para>See http://mycomponent.blogspot.com/2009/05/get-mac-address-in-c-from-ip.html 99 /// </para> 100 /// </remarks> 101 /// <param name="macAddress">The MAC address of the host which has to be 102 /// woken up.</param> 103 private static void Wakeup(string macAddress) 104 { 105 WOLUdpClient client = new WOLUdpClient(); 106 client.Connect( 107 new IPAddress(0xffffffff), //255.255.255.255 i.e broadcast 108 0x2fff); // port = 12287 109 // Set the socketoptions 110 if (client.IsClientInBrodcastMode()) 111 { 112 int byteCount = 0; 113 // buffer to be sent: 114 // 6 bytes each with 255 + 16 times mac each 6 bytes 115 byte[] bytes = new byte[102]; 116 // The packet begins with 6 bytes trailer of FF bytes which is 117 // followed by 16 times repeated MAC address of the target device 118 // (i.e. the device that should be switched on). MAC Address is 119 // used as an identifier in the packet, because that is the only 120 // valuable identification that is available when the PC is not 121 // running. MAC Address is assigned by the manufacturer (it is 122 // a layer 2 - Data link layer identifier) and it stored in the 123 // flash memory of the network card itself, so the network card 124 // can perform the comparison very easily. It cannot use an IP 125 // address, because network card simply does not have one when 126 // PC is not running - IP address is a layer 3 - network layer 127 // identifier, which means it is assigned by the OS. 128 // You may also ask why the MAC address is repeated 16 times? 129 // As mentioned above the network card scans all packets that 130 // are coming in and it does not support any protocols of higher 131 // levels (TCP, HTTP, etc.) - it will literally go through all 132 // bytes in the packet and if it finds the "magic packet" 133 // sequence anywhere in the data or even a packet header, it 134 // will turn on the PC. Imagine that the packet did not repeat 135 // the MAC Address, so it would only utilise 6 bytes of FF and 136 // then 6 bytes of the MAC address. This 12 bytes combination 137 // may sooner or later appear in your network communication 138 // (in a file transfer, incoming email, a picture, etc.). 12 139 // bytes is just not enough, which is why the MAC address is 140 // repeated 16 times giving the packet solid 102 bytes. The 141 // probability that those 102 bytes will unintentionally appear 142 // in transferred data is exponentially lower (there are 143 // 256^102 different packets which should be safe enough). 144 145 // First 6 bytes should be 0xFF 146 for (int trailer = 0; trailer < 6; trailer++) 147 { 148 bytes[byteCount++] = 0xFF; 149 } 150 // Repeat MAC 16 times 151 for (int macPackets = 0; macPackets < 16; macPackets++) 152 { 153 int i = 0; 154 for (int macBytes = 0; macBytes < 6; macBytes++) 155 { 156 bytes[byteCount++] = 157 byte.Parse(macAddress.Substring(i, 2), 158 NumberStyles.HexNumber); 159 i += 2; 160 } 161 } 162 163 // Send wake up packet (the magic packet!) 164 int returnValue = client.Send(bytes, byteCount); 165 Console.WriteLine(returnValue + " bytes sent to " + macAddress + 166 Environment.NewLine + "Check if it's woken up. If not, try again!" + 167 Environment.NewLine); 168 } 169 else 170 { 171 Console.WriteLine("Remote client could not be set in broadcast mode!"); 172 } 173 } // end Wakeup 174 175 } // end class WakeUpOnLan 176 177 // ************************************************************************* 178 /// <summary> 179 /// A <see cref="UdpClient"/> class to set the client to broadcast mode. 180 /// </summary> 181 /// <remarks> 182 /// <para> 183 /// This class just sets the SocketOption to 184 /// <see cref="SocketOptionName.Broadcast"/> mode. 185 /// </para> 186 /// </remarks> 187 public class WOLUdpClient : UdpClient 188 { 189 // ********************************************************************* 190 /// <summary> 191 /// Initializes a new instance of <see cref="WOLUdpClient"/>. 192 /// </summary> 193 public WOLUdpClient() : base() 194 { 195 } 196 197 // ********************************************************************* 198 /// <summary> 199 /// Sets up the UDP client to broadcast packets. 200 /// </summary> 201 /// <returns><see langword="true"/> if the UDP client is set in 202 /// broadcast mode.</returns> 203 public bool IsClientInBrodcastMode() 204 { 205 bool broadcast = false; 206 if (this.Active) 207 { 208 try 209 { 210 this.Client.SetSocketOption(SocketOptionLevel.Socket, 211 SocketOptionName.Broadcast, 0); 212 broadcast = true; 213 } 214 catch 215 { 216 broadcast = false; 217 } 218 } 219 return broadcast; 220 } 221 222 } // end class WOLUdpClient 223 } // end namespace Yours.Truly
Monday, May 11, 2009
Wake On LAN (WOL) in C#
Get MAC Address in C# from IP Address/Hostname
I was hoping to find something to get MAC address of a machine given its IP address or hostname. There could be multiple ways to do the same. But I thought I'll give the "nbtstat" a chance. nbtstat is a command in windows which gets you the details about protocol statistics and current TCP/IP connections using NBT (NetBIOS over TCP/IP). Here is a small program in C# which does the exact same thing: (If you want just the exe, let me know via a comment here and I'll send you the executable.) 1 // No copyrights(c). Use as you wish! 2 3 using System; 4 using System.Diagnostics; 5 using System.Net; 6 using System.Net.NetworkInformation; 7 using System.Runtime.InteropServices; 8 using System.Text; 9 10 namespace Yours.Truly 11 { 12 // ************************************************************************* 13 /// <summary> 14 /// A class to get the MAC address from IP address. The same class can be 15 /// modified a little to get the MAC address from the specified hostname. 16 /// </summary> 17 public class GetMacAddressFromIPAddress 18 { 19 /// <summary> Ping timeout (in ms) </summary> 20 private const int PING_TIMEOUT = 1000; 21 22 // ********************************************************************* 23 /// <summary> 24 /// Initializes a new instance of <see cref="GetMacAddressFromIPAddress"/>. 25 /// </summary> 26 public GetMacAddressFromIPAddress() 27 { 28 } 29 30 // ********************************************************************* 31 /// <summary> 32 /// Gets the MAC address from specified <paramref name="IPAddress"/> 33 /// using nbtstat in hyphen (-) separated format. 34 /// </summary> 35 /// <remarks> 36 /// <para> 37 /// The same class can be modified to accept hostname and then resolve 38 /// the hostname to Ip address to get the MAC address or just pass "-a" 39 /// argument to "nbtstat" to get the mac address from hostname. If you 40 /// want to find the MAC address from only the IP address change the 41 /// switch to "-A". 42 /// </para> 43 /// <para> 44 /// The current program can resolve both hostname as well as IP address 45 /// to MAC address. The "-a" argument can actually accept both IP address 46 /// as well as hostname. 47 /// </para> 48 /// </remarks> 49 /// <param name="ipAddress">The IP address or hostname for the machine 50 /// for which the MAC address is desired.</param> 51 /// <returns>A string containing the MAC address if MAC address could be 52 /// found.An empty or null string otherwise.</returns> 53 private string GetMacAddress(string ipAddress) 54 { 55 string macAddress = string.Empty; 56 57 if (!IsHostAccessible(ipAddress)) return null; 58 try 59 { 60 ProcessStartInfo processStartInfo = new ProcessStartInfo(); 61 Process process = new Process(); 62 processStartInfo.FileName = "nbtstat"; 63 processStartInfo.RedirectStandardInput = false; 64 processStartInfo.RedirectStandardOutput = true; 65 processStartInfo.Arguments = "-a " + ipAddress; 66 processStartInfo.UseShellExecute = false; 67 process = Process.Start(processStartInfo); 68 69 int Counter = -1; 70 71 while (Counter <= -1) 72 { 73 // Look for the words "mac address" in the output. 74 // The output usually looks likes this: 75 76 // Local Area Connection: 77 //Node IpAddress: [13.15.111.222] Scope Id: [] 78 79 // NetBIOS Remote Machine Name Table 80 81 // Name Type Status 82 // -------------------------------------------- 83 // SAMGLS0790W <00> UNIQUE Registered 84 // SAMPLS0790W <20> UNIQUE Registered 85 // NA <00> GROUP Registered 86 87 // MAC Address = 00-21-70-2B-A5-43 88 89 Counter = 90 macAddress.Trim().ToLower().IndexOf("mac address", 0); 91 if (Counter > -1) 92 { 93 break; 94 } 95 macAddress = process.StandardOutput.ReadLine(); 96 } 97 process.WaitForExit(); 98 macAddress = macAddress.Trim(); 99 } 100 catch (Exception e) 101 { 102 // Something unexpected happened? Inform the user 103 // The possibilities are: 104 // 1.That the machine is not on the network currently 105 // 2. The IP address/hostname supplied are not on the same network 106 // 3. The host was not found on the same subnet or could not be 107 // resolved 108 Console.WriteLine("Failed because:" + e.ToString()); 109 } 110 111 return macAddress; 112 } 113 114 #region Getting MAC from ARP 115 116 [DllImport("iphlpapi.dll", ExactSpelling = true)] 117 static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, 118 ref uint PhyAddrLen); 119 120 // ********************************************************************* 121 /// <summary> 122 /// Gets the MAC address from ARP table in colon (:) separated format. 123 /// </summary> 124 /// <param name="hostNameOrAddress">Host name or IP address of the 125 /// remote host for which MAC address is desired.</param> 126 /// <returns>A string containing MAC address; null if MAC address could 127 /// not be found.</returns> 128 private string GetMACAddressFromARP(string hostNameOrAddress) 129 { 130 if (!IsHostAccessible(hostNameOrAddress)) return null; 131 132 IPHostEntry hostEntry = Dns.GetHostEntry(hostNameOrAddress); 133 if (hostEntry.AddressList.Length == 0) 134 return null; 135 136 byte[] macAddr = new byte[6]; 137 uint macAddrLen = (uint) macAddr.Length; 138 if (SendARP((int) hostEntry.AddressList[0].Address, 0, macAddr, 139 ref macAddrLen) != 0) 140 return null; 141 142 StringBuilder macAddressString = new StringBuilder(); 143 for (int i = 0; i < macAddr.Length; i++) 144 { 145 if (macAddressString.Length > 0) 146 macAddressString.Append(":"); 147 148 macAddressString.AppendFormat("{0:x2}", macAddr[i]); 149 } 150 151 return macAddressString.ToString(); 152 } // end GetMACAddressFromARP 153 154 #endregion Getting MAC from ARP 155 156 // ********************************************************************* 157 /// <summary> 158 /// Checks to see if the host specified by 159 /// <paramref name="hostNameOrAddress"/> is currently accessible. 160 /// </summary> 161 /// <param name="hostNameOrAddress">Host name or IP address of the 162 /// remote host for which MAC address is desired.</param> 163 /// <returns><see langword="true" /> if the host is currently accessible; 164 /// <see langword="false"/> otherwise.</returns> 165 private static bool IsHostAccessible(string hostNameOrAddress) 166 { 167 Ping ping = new Ping(); 168 PingReply reply = ping.Send(hostNameOrAddress, PING_TIMEOUT); 169 return reply.Status == IPStatus.Success; 170 } 171 172 // ********************************************************************* 173 /// <summary> 174 /// The netry point for the application. 175 /// </summary> 176 /// <param name="args">An array of command line arguments.</param> 177 [STAThread] 178 static void Main(string[] args) 179 { 180 bool macRequired = true; 181 while (macRequired) 182 { 183 Console.WriteLine("Enter the IP address for which mac address is " + 184 "required:(Enter exit to quit the program.)"); 185 string ipAddress = Console.ReadLine(); 186 StringComparer cp = StringComparer.OrdinalIgnoreCase; 187 if (cp.Compare(ipAddress, "Exit") == 0) break; 188 189 GetMacAddressFromIPAddress getMacAddress = 190 new GetMacAddressFromIPAddress(); 191 192 Console.WriteLine("Please wait while I try to find the MAC address..."); 193 // You may also use the ARP table. Call GetMACAddressFromARP here 194 string MacAddress = getMacAddress.GetMacAddress(ipAddress); 195 196 Console.WriteLine(MacAddress); 197 } // end while 198 } 199 200 } // end class GetMacAddressFromIPAddress 201 202 } // end namespace Yours.Truly