I am trying to get the MAC address of another device using the SendARP function and this code:

[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(System.Net.IPAddress DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);

private void btnMAC_Click(object sender, EventArgs e)
{
    string mac = "";
    IPHostEntry hostEntry = Dns.GetHostEntry(IPaddress);

    byte[] macAddr = new byte[6];
    uint macAddrLen = (uint)macAddr.Length;

    int dwRetVal = SendARP(hostEntry.AddressList[0], 0, macAddr, ref macAddrLen);

    if (dwRetVal == 0)
    {
        StringBuilder macAddressString = new StringBuilder();
        for (int i = 0; i < macAddr.Length; i++)
        {
            if (macAddressString.Length > 0)
                macAddressString.Append(":");

            macAddressString.AppendFormat("{0:x2}", macAddr[i]);
        }

        mac = macAddressString.ToString();
    }
    else
    {
        lblMACaddress.Text = "Invalid";
    }
}

The MAC address it is returning is completely wrong. I referenced this question, C++ SendARP returns wrong mac address? but the answer to that question really seemed to be about the return stack being cached when getting out of the function, but I'm doing everything within my function.

I must be missing some basic concepts here that I'm not understanding from other references.

---EDIT--- Changed my function to be like this due to possible wrong parameter type:

        string ip = txtIP1.Text + "." + txtIP2.Text + "." + txtIP3.Text + "." + txtIP4.Text;
        IPAddress dst = IPAddress.Parse(ip);
        int intAddress = BitConverter.ToInt32(dst.GetAddressBytes(), 0);

        byte[] macAddr = new byte[6];
        uint macAddrLen = (uint)macAddr.Length;

        if (SendARP(intAddress, 0, macAddr, ref macAddrLen) != 0)
        {
            lblMACaddress.Text = "SendARP failed.";
            return;
        }

        string[] str = new string[(int)macAddrLen];

        for (int i = 0; i < macAddrLen; i++)
            str[i] = macAddr[i].ToString("x2");

        string mac = string.Join(":", str);

Now the issue is when I use my own computer's IP I get the correct MAC but when I use the IP of a different computer on my LAN I get the SendARP failed exception thrown. Any ideas why this is happening?

有帮助吗?

解决方案

I think your p-invoke is wrong. The WINAPI definition of this function passes

this

typedef struct {
  union {
    struct {
      u_char s_b1,s_b2,s_b3,s_b4;
    } S_un_b;
    struct {
      u_short s_w1,s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
} IPAddr;

Which I seriously doubt has the same memory layout as the IPAddress class.

Here is a point to get started:

http://www.pinvoke.net/default.aspx/iphlpapi.sendarp

If that doesn't work, you could always marshall the structure yourself using explicit memory layouts, or just use IntPtr.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top