C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: GetAdaptersInfoの結果を取得できない


(過去ログ 162 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■93544 / inTopicNo.1)  GetAdaptersInfoの結果を取得できない
  
□投稿者/ kiku (155回)-(2019/12/20(Fri) 15:10:36)

分類:[C#] 

動作環境
・WindowsCE6.0
・.NETcompactframework3.5

CE本体のMACアドレスが取得したく、
Win32APIのGetAdaptersInfoから取得できることがわかったため、
動作確認しているのですが、うまく取得できていない状況です。

CE機にもってくる前に、Win10、C#の環境で
GetAdaptersInfoで正しく動作することを確認した上で、
CE機に持ってきていますが
うまく移植ができていない状況です。

おそらく構造体の定義が間違っていると思っているのですが、
対処方法がわかりません。
知見のある方、お教え頂きますと幸いです。

下記にCE機上のソースコードを貼ります。
ソースコード上にコメント入れてあります。


using System.Runtime.InteropServices;

namespace SmartDeviceProject1
{
    public partial class Form1 : Form
    {
        const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
        const int MAX_ADAPTER_NAME_LENGTH = 256;
        const int MAX_ADAPTER_ADDRESS_LENGTH = 8;

        const int ERROR_BUFFER_OVERFLOW = 111;

        const int MIB_IF_TYPE_OTHER = 1;
        const int MIB_IF_TYPE_ETHERNET = 6;
        const int MIB_IF_TYPE_TOKENRING = 9;
        const int MIB_IF_TYPE_FDDI = 15;
        const int MIB_IF_TYPE_PPP = 23;
        const int MIB_IF_TYPE_LOOPBACK = 24;
        const int MIB_IF_TYPE_SLIP = 28;

        //[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        //●上記ビルドエラーとなるため、下記のようにCharSet.Unicodeに変更
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct IP_ADDRESS_STRING
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string Address;
        }

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

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public 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;
        }

        //●実機にdllが存在することを確認
        [DllImport("iphlpapi.dll", CharSet = CharSet.Unicode)]
        //public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);
        //●CE機ではInt64は扱えないと考え、Int32に変更
        public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int32 pBufOutLen);

        public Form1()
        {
            InitializeComponent();
            GetAdapters();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            GetAdapters();
        }

        public static void GetAdapters()
        {
            //long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            //●上記ビルドエラーとなったため、下記のようにintへ変更
            int structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            //IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));
            //●上記ビルドエラーとなったため、下記のようにintへキャスト
            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);
                //●retの結果は0になる
            } // 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));

                    // ***Do something with the data HERE!***
                    Console.WriteLine("\n");
                    Console.WriteLine("Index: {0}", entry.Index.ToString());

                    // Adapter Type
                    string tmpString = string.Empty;
                    //●実機では
                    //  1回目:entry.Type=0x00000000
                    //  2回目:entry.Type=0x000001e8
                    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.Address.Length - 1; i++)
                    {
                        tmpString += string.Format("{0:X2}-", entry.Address[i]);
                    }
                    Console.WriteLine("MAC Address    : {0}{1:X2}\n", tmpString, entry.Address[entry.Address.Length - 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

    }
}

引用返信 編集キー/
■93545 / inTopicNo.2)  Re[1]: GetAdaptersInfoの結果を取得できない
□投稿者/ Hongliang (939回)-(2019/12/20(Fri) 16:06:31)
試す環境もありませんしあんまりちゃんと見てませんが。

> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
> public struct IP_ADDRESS_STRING
> {
>     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
>     public string Address;
> }
https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms891174%28v%3dmsdn.10%29
ドキュメントによるとchar Address[4 * 4]だそうです。
CharSet.UnicodeでのByValTStrはwchar_tになりますから定義が間違ってますね。
UnmanagedType.ByValArrayでbyte[]として扱うことになるかなぁ。
文字列化はEncoding.Default.GetString()したうえで、IndexOf('0')の前までをSubstringとかすることになりますかね。

> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
> public 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)]
https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms891170%28v%3dmsdn.10%29
IP_ADDRESS_STRINGと同様。

> //●実機にdllが存在することを確認
> [DllImport("iphlpapi.dll", CharSet = CharSet.Unicode)]
> //public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);
> //●CE機ではInt64は扱えないと考え、Int32に変更
> public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int32 pBufOutLen);
https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa450394%28v%3Dmsdn.10%29
Windows APIにおけるULONGは32bit符号なし整数値です。

引用返信 編集キー/
■93552 / inTopicNo.3)  Re[2]: GetAdaptersInfoの結果を取得できない
□投稿者/ kiku (156回)-(2019/12/20(Fri) 18:41:31)
No93545 (Hongliang さん) に返信
> 試す環境もありませんしあんまりちゃんと見てませんが。

ご指摘の通りで動作することを確認しました。
大変助かりました。
ありがとうございます。
引用返信 編集キー/
■93553 / inTopicNo.4)  Re[3]: GetAdaptersInfoの結果を取得できない
□投稿者/ kiku (157回)-(2019/12/20(Fri) 18:41:58)
解決済みチェック
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -