在C#for Windows CE 6.0中收集本地网络信息的问题

时间:2017-07-17 11:23:10

标签: c# windows networking windows-ce gateway

我正在进行跨平台开发,并且在尝试使用Windows CE 6.0上的C#收集本地网络信息时遇到问题。我正在收集本地IP地址和网关IP地址等信息。我获取本地IP地址的方法在所有平台上都能正常工作,但获取网关IP地址的方法并不适用于CE 6.0,以下是我所拥有的

    private IPAddress GetGatewayInfo()       
    {
        //Console.WriteLine("Gateways");
        NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
        foreach (NetworkInterface adapter in adapters)
        {
            IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
            GatewayIPAddressInformationCollection addresses = adapterProperties.GatewayAddresses;
            if (addresses.Count > 0)
            {
                foreach (GatewayIPAddressInformation address in addresses)
                {
                    Console.WriteLine("Gateway IP is : {0}", address.Address);
                    return address.Address;

                }

            }

        }
        return null;
    }

经过一些研究后,我发现CE上不支持像GetAllNetworkInterfaces()这样的方法,我找到了获取此信息的另一种方法,如下所示

class libGetAdaptersInfo
{
    [DllImport("iphlpapi.dll")]
    private static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);

    private const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
    private const int ERROR_BUFFER_OVERFLOW = 111;
    private const int MAX_ADAPTER_NAME_LENGTH = 256;
    private const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
    private const int MIB_IF_TYPE_OTHER = 1;
    private const int MIB_IF_TYPE_ETHERNET = 6;
    private const int MIB_IF_TYPE_TOKENRING = 9;
    private const int MIB_IF_TYPE_FDDI = 15;
    private const int MIB_IF_TYPE_PPP = 23;
    private const int MIB_IF_TYPE_LOOPBACK = 24;
    private const int MIB_IF_TYPE_SLIP = 28;

    [StructLayout(LayoutKind.Sequential)]
    private struct IP_ADDRESS_STRING
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string Address;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct IP_ADDR_STRING
    {
        public IntPtr Next;
        public IP_ADDRESS_STRING IpAddress;
        public IP_ADDRESS_STRING IpMask;
        public Int32 Context;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct IP_ADAPTER_INFO
    {
        public IntPtr Next;
        public Int32 ComboIndex;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
        public string AdapterName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
        public string AdapterDescription;
        public UInt32 AddressLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
        public byte[] Address;
        public Int32 Index;
        public UInt32 Type;
        public UInt32 DhcpEnabled;
        public IntPtr CurrentIpAddress;
        public IP_ADDR_STRING IpAddressList;
        public IP_ADDR_STRING GatewayList;
        public IP_ADDR_STRING DhcpServer;
        public bool HaveWins;
        public IP_ADDR_STRING PrimaryWinsServer;
        public IP_ADDR_STRING SecondaryWinsServer;
        public Int32 LeaseObtained;
        public Int32 LeaseExpires;
    }

    public static void GetAdapters()
    {
        long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
        IntPtr pArray = Marshal.AllocHGlobal((int)new IntPtr(structSize));

        int ret = GetAdaptersInfo(pArray, ref structSize);

        if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
        {
            // Buffer was too small, reallocate the correct size for the buffer.
            pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));

            ret = GetAdaptersInfo(pArray, ref structSize);
        } // if

        if (ret == 0)
        {
            // Call Succeeded
            IntPtr pEntry = pArray;

            do
            {
                // Retrieve the adapter info from the memory address
                IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));


                Console.WriteLine("\n");
                Console.WriteLine("Index: {0}", entry.Index.ToString());

                // Adapter Type
                string tmpString = string.Empty;
                switch (entry.Type)
                {
                    case MIB_IF_TYPE_ETHERNET: tmpString = "Ethernet"; break;
                    case MIB_IF_TYPE_TOKENRING: tmpString = "Token Ring"; break;
                    case MIB_IF_TYPE_FDDI: tmpString = "FDDI"; break;
                    case MIB_IF_TYPE_PPP: tmpString = "PPP"; break;
                    case MIB_IF_TYPE_LOOPBACK: tmpString = "Loopback"; break;
                    case MIB_IF_TYPE_SLIP: tmpString = "Slip"; break;
                    default: tmpString = "Other/Unknown"; break;
                } // switch
                Console.WriteLine("Adapter Type: {0}", tmpString);

                Console.WriteLine("Name: {0}", entry.AdapterName);
                Console.WriteLine("Desc: {0}\n", entry.AdapterDescription);

                Console.WriteLine("DHCP Enabled: {0}", (entry.DhcpEnabled == 1) ? "Yes" : "No");

                if (entry.DhcpEnabled == 1)
                {
                    Console.WriteLine("DHCP Server : {0}", entry.DhcpServer.IpAddress.Address);

                    // Lease Obtained (convert from "time_t" to C# DateTime)
                    DateTime pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseObtained).ToLocalTime();
                    Console.WriteLine("Lease Obtained: {0}", pdatDate.ToString());

                    // Lease Expires (convert from "time_t" to C# DateTime)
                    pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseExpires).ToLocalTime();
                    Console.WriteLine("Lease Expires : {0}\n", pdatDate.ToString());
                } // if DhcpEnabled

                Console.WriteLine("IP Address     : {0}", entry.IpAddressList.IpAddress.Address);
                Console.WriteLine("Subnet Mask    : {0}", entry.IpAddressList.IpMask.Address);
                Console.WriteLine("Default Gateway: {0}", entry.GatewayList.IpAddress.Address);

                // MAC Address (data is in a byte[])
                tmpString = string.Empty;
                for (int i = 0; i < entry.AddressLength - 1; i++)
                {
                    tmpString += string.Format("{0:X2}-", entry.Address[i]);
                }
                Console.WriteLine("MAC Address    : {0}{1:X2}\n", tmpString, entry.Address[entry.AddressLength - 1]);

                Console.WriteLine("Has WINS: {0}", entry.HaveWins ? "Yes" : "No");
                if (entry.HaveWins)
                {
                    Console.WriteLine("Primary WINS Server  : {0}", entry.PrimaryWinsServer.IpAddress.Address);
                    Console.WriteLine("Secondary WINS Server: {0}", entry.SecondaryWinsServer.IpAddress.Address);
                } // HaveWins

                // Get next adapter (if any)
                pEntry = entry.Next;

            }
            while (pEntry != IntPtr.Zero);

            Marshal.FreeHGlobal(pArray);

        } // if
        else
        {
            Marshal.FreeHGlobal(pArray);
            throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
        }

    } // GetAdapters

上述方法在Windows 7上工作正常并且打印了所有正确的值但是当我在CE上测试它时仍然存在问题,例如所有值都表示它们是未知/空的,当尝试获取时,索引超出范围异常MAC地址信息,并在程序结束时崩溃,并显示&#34;不支持的异常&#34;。我现在非常难过,因为它在第7场比赛中表现非常好,所以我不确定下一步该尝试什么,因为这是我能找到的唯一可以在CE上工作的方法,有谁知道我是怎么做的可以解决这些问题或知道另一种方法来获取网关IP地址?感谢

1 个答案:

答案 0 :(得分:1)

GetAdaptersInfo应该有效,但我看到P / Invoke定义存在一些问题:

  • 在Windows CE上,GetAdaptersInfo的第二个参数是指向32位整数的指针,而不是64位
  • iphlpapi上下文中的字符串是C样式的char数组,因此使用UnmanagedType.ByValTStr选择的2字节Unicode的CE默认值将不起作用。在包含字符串
  • 的所有结构的CharSet = CharSet.Ansi属性中指定StructLayout
  • HaveWins被指定为.NET bool,但如果我没记错的话,它会被编组为单个字节。将[MarshalAs(UnmanagedType.Bool)]粘贴在前面,或更改为int以正确映射到基础类型。

我可能错过了一些东西,所以请根据CE定义彻底检查您的代码。一个好的起点可能是https://msdn.microsoft.com/en-us/library/ms891170.aspx(CE 5.0文档,但与6.0相同)。