/// <summary> /// Get the IP and MAC addresses of all known devices on the LAN /// </summary> /// <remarks> /// 1) This table is not updated often - it can take some human-scale time /// to notice that a device has dropped off the network, or a new device /// has connected. /// 2) This discards non-local devices if they are found - these are multicast /// and can be discarded by IP address range. /// </remarks> /// <returns></returns> private static Dictionary <IPAddress, PhysicalAddress> GetAllDevicesOnLan() { var all = new Dictionary <IPAddress, PhysicalAddress> { { GetIpAddress(), GetMacAddress() } }; // Add this PC to the list... var spaceForNetTable = 0; // Get the space needed // We do that by requesting the table, but not giving any space at all. // The return value will tell us how much we actually need. GetIpNetTable(IntPtr.Zero, ref spaceForNetTable, false); // Allocate the space // We use a try-finally block to ensure release. var rawTable = IntPtr.Zero; try { rawTable = Marshal.AllocCoTaskMem(spaceForNetTable); // Get the actual data var errorCode = GetIpNetTable(rawTable, ref spaceForNetTable, false); if (errorCode != 0) { // Failed for some reason - can do no more here. throw new Exception($"Unable to retrieve network table. Error code {errorCode}"); } // Get the rows count var rowsCount = Marshal.ReadInt32(rawTable); var currentBuffer = new IntPtr(rawTable.ToInt64() + Marshal.SizeOf(typeof(int))); // Convert the raw table to individual entries var rows = new MibIpnetrow[rowsCount]; for (var index = 0; index < rowsCount; index++) { rows[index] = (MibIpnetrow)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() + index * Marshal.SizeOf(typeof(MibIpnetrow)) ), typeof(MibIpnetrow)); } // Define the dummy entries list (we can discard these) var virtualMac = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 }); var broadcastMac = new PhysicalAddress(new byte[] { 255, 255, 255, 255, 255, 255 }); foreach (var row in rows) { var ip = new IPAddress(BitConverter.GetBytes(row.dwAddr)); byte[] rawMac = { row.mac0, row.mac1, row.mac2, row.mac3, row.mac4, row.mac5 }; var pa = new PhysicalAddress(rawMac); if (!pa.Equals(virtualMac) && !pa.Equals(broadcastMac) && !IsMulticast(ip)) { //Console.WriteLine("IP: {0}\t\tMAC: {1}", ip.ToString(), pa.ToString()); if (!all.ContainsKey(ip)) { all.Add(ip, pa); } } } } finally { // Release the memory. Marshal.FreeCoTaskMem(rawTable); } return(all); }
public static List<string> GetRouterMac(string ipRequest = "192.168.1.1") { // The number of bytes needed. int bytesNeeded = 0; // The result from the API call. int result = GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false); // Call the function, expecting an insufficient buffer. if (result != ErrorInsufficientBuffer) { // Throw an exception. throw new Win32Exception(result); } // Allocate the memory, do it in a try/finally block, to ensure // that it is released. IntPtr buffer = IntPtr.Zero; // Try/finally. try { // Allocate the memory. buffer = Marshal.AllocCoTaskMem(bytesNeeded); // Make the call again. If it did not succeed, then // raise an error. result = GetIpNetTable(buffer, ref bytesNeeded, false); // If the result is not 0 (no error), then throw an exception. if (result != 0) { // Throw an exception. throw new Win32Exception(result); } // Now we have the buffer, we have to marshal it. We can read // the first 4 bytes to get the length of the buffer. int entries = Marshal.ReadInt32(buffer); // Increment the memory pointer by the size of the int. IntPtr currentBuffer = new IntPtr(buffer.ToInt64() + Marshal.SizeOf(typeof(int))); // Allocate an array of entries. MibIpnetrow[] table = new MibIpnetrow[entries]; // Cycle through the entries. for (int index = 0; index < entries; index++) { // Call PtrToStructure, getting the structure information. table[index] = (MibIpnetrow)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() + (index * Marshal.SizeOf(typeof(MibIpnetrow)))), typeof(MibIpnetrow)); } List<string> list = new List<string>(); for (int index = 0; index < entries; index++) { MibIpnetrow row = table[index]; IPAddress ip = new IPAddress(BitConverter.GetBytes(row.dwAddr)); StringBuilder sbMac = new StringBuilder(); sbMac.Append(row.mac0.ToString("X2") + '-'); sbMac.Append(row.mac1.ToString("X2") + '-'); sbMac.Append(row.mac2.ToString("X2") + '-'); sbMac.Append(row.mac3.ToString("X2") + '-'); sbMac.Append(row.mac4.ToString("X2") + '-'); sbMac.Append(row.mac5.ToString("X2")); if (ip.ToString() == ipRequest) { list.Add(sbMac.ToString()); } } //if (list.Count == 0) //{ // throw new Exception("不存在的IP地址: " + ipRequest); //} return list; } finally { // Release the memory. FreeMibTable(buffer); } }