简体   繁体   English

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

[英]Issues gathering local network information in C# for Windows CE 6.0

I'm doing some cross platform development and am having issues trying to gather local network information using C# on Windows CE 6.0. 我正在做一些跨平台开发,在尝试在Windows CE 6.0上使用C#收集本地网络信息时遇到问题。 I'm gathering information such as local IP address and gateway IP address. 我正在收集诸如本地IP地址和网关IP地址之类的信息。 My method to get the local IP address works fine on all platforms but the method to get the gateway IP address doesn't work on CE 6.0, below is what I have 我的获取本地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;
    }

So after some research I found methods like GetAllNetworkInterfaces() aren't supported on CE and I found another way to get this information which is listed below 因此,经过一些研究,我发现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

The above method worked fine on Windows 7 and printed all correct values but when I tested it on CE I still had issues, such as all values saying they are unknown/empty, an index out of range exception when trying to get the MAC address information, and crashing at the end of the program with an "Not supported exception". 上面的方法在Windows 7上可以正常工作并打印所有正确的值,但是当我在CE上对其进行测试时,我仍然遇到问题,例如所有值都表示它们是未知/空,试图获取MAC地址信息时出现索引超出范围的异常,并在程序结尾以“不支持的异常”崩溃。 I'm pretty stumped now as it works perfectly fine on win 7 so I'm not sure what to try next as this was the only method I could find that was supposed to work on CE, does anyone know how I could fix these issues or know of another method to get the gateway IP address? 我现在很困惑,因为它在胜利7上可以很好地工作,所以我不确定下一步该怎么做,因为这是我发现可以在CE上运行的唯一方法,有人知道我可以解决这些问题吗?或知道另一种获取网关IP地址的方法? thanks 谢谢

GetAdaptersInfo should work, but I see a few issues with the P/Invoke definitions: GetAdaptersInfo应该可以工作,但是我发现P / Invoke定义存在一些问题:

  • On Windows CE, the second parameter to GetAdaptersInfo is a pointer to a 32-bit integer, not 64-bit 在Windows CE上, GetAdaptersInfo的第二个参数是指向32位整数而不是64位整数的指针
  • Strings in iphlpapi context are C-style char arrays, so the CE default of 2-byte Unicode selected with UnmanagedType.ByValTStr won't work. iphlpapi上下文中的字符串是C样式的char数组,因此使用UnmanagedType.ByValTStr选择的CE默认2字节Unicode将不起作用。 Specify CharSet = CharSet.Ansi in the StructLayout attribute on all structs that contain strings 在所有包含字符串的结构上的StructLayout属性中指定CharSet = CharSet.Ansi
  • HaveWins is specified as a .NET bool , but if I remember correctly this is marshalled as a single byte. HaveWins被指定为.NET bool ,但是如果我没记错的话,它被编组为一个字节。 Stick a [MarshalAs(UnmanagedType.Bool)] in front, or change to int to map correctly to the underlying type. [MarshalAs(UnmanagedType.Bool)]放在前面,或更改为int以正确映射到基础类型。

I may have missed something, so do check your code thoroughly against the CE definitions. 我可能错过了一些内容,因此请务必根据CE定义彻底检查您的代码。 A good place to start might be https://msdn.microsoft.com/en-us/library/ms891170.aspx (CE 5.0 documentation, but same as 6.0). 一个不错的起点可能是https://msdn.microsoft.com/zh-cn/library/ms891170.aspx(CE 5.0文档,但与6.0相同)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM