GetAdaptersAddresses 函式 (iphlpapi.h)

GetAdaptersAddresses函式會擷取與本機電腦上的配接器相關聯的位址。

語法

IPHLPAPI_DLL_LINKAGE ULONG GetAdaptersAddresses(
  [in]      ULONG                 Family,
  [in]      ULONG                 Flags,
  [in]      PVOID                 Reserved,
  [in, out] PIP_ADAPTER_ADDRESSES AdapterAddresses,
  [in, out] PULONG                SizePointer
);

參數

[in] Family

要擷取之位址的位址系列。 此參數必須是下列其中一個值。

意義
AF_UNSPEC
0
傳回與已啟用 IPv4 或 IPv6 之介面卡相關聯的 IPv4 和 IPv6 位址。
AF_INET
2
只傳回與已啟用 IPv4 之介面卡相關聯的 IPv4 位址。
AF_INET6
23
只傳回與已啟用 IPv6 之介面卡相關聯的 IPv6 位址。

[in] Flags

要擷取的網址類別型。 可能的值定義于 Iptypes.h 標頭檔中。 請注意, Iptypes.h 標頭檔會自動包含在 Iphlpapi.h中,不應直接使用。

此參數是下列值的組合。 如果此參數為零,則會傳回單播、任何播和多播 IP 位址。

意義
GAA_FLAG_SKIP_UNICAST
0x0001
請勿傳回單播位址。
GAA_FLAG_SKIP_ANYCAST
0x0002
請勿傳回 IPv6 任何廣播位址。
GAA_FLAG_SKIP_MULTICAST
0x0004
請勿傳回多播位址。
GAA_FLAG_SKIP_DNS_SERVER
0x0008
請勿傳回 DNS 伺服器的位址。
GAA_FLAG_INCLUDE_PREFIX
0x0010
傳回此配接器上的 IP 位址前置詞清單。 設定此旗標時,會針對 IPv6 和 IPv4 位址傳回 IP 位址前置詞。

Windows XP 支援此旗標 SP1 和更新版本。

GAA_FLAG_SKIP_FRIENDLY_NAME
0x0020
請勿傳回配接器易記名稱。
GAA_FLAG_INCLUDE_WINS_INFO
0x0040
傳回 Windows 網際網路名稱服務 (WINS) 伺服器的位址。

Windows Vista 和更新版本支援此旗標。

GAA_FLAG_INCLUDE_GATEWAYS
0x0080
傳回預設閘道的位址。

Windows Vista 和更新版本支援此旗標。

GAA_FLAG_INCLUDE_ALL_INTERFACES
0x0100
傳回所有 NDIS 介面的位址。

Windows Vista 和更新版本支援此旗標。

GAA_FLAG_INCLUDE_ALL_COMPARTMENTS
0x0200
傳回所有路由區間中的位址。

目前不支援此旗標,並保留供日後使用。

GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER
0x0400
傳回以通道系結順序排序的配接器位址。 Windows Vista 和更新版本支援此旗標。

[in] Reserved

目前未使用此參數,但保留供未來系統使用。 呼叫的應用程式應該傳遞此參數的 Null

[in, out] AdapterAddresses

緩衝區的指標,其中包含成功傳回時 IP_ADAPTER_ADDRESSES 結構的連結清單。

[in, out] SizePointer

變數的指標,指定 AdapterAddresses所指向之緩衝區的大小。

傳回值

如果函式成功,傳回值 會ERROR_SUCCESS ( 定義為與 NO_ERROR) 相同的值。

如果函式失敗,傳回值就是下列其中一個錯誤碼。

傳回碼 描述
ERROR_ADDRESS_NOT_ASSOCIATED
位址尚未與網路端點相關聯。 DHCP 租用資訊可供使用。
ERROR_BUFFER_OVERFLOW
SizePointer參數所指示的緩衝區大小太小,無法保存配接器資訊,或AdapterAddresses參數為NullSizePointer參數傳回的指向緩衝區所需的大小,以保存配接器資訊。
ERROR_INVALID_PARAMETER
其中一個參數無效。 下列任一條件會傳回此錯誤: SizePointer 參數為 NullAddress 參數未 AF_INETAF_INET6AF_UNSPEC,或所要求參數的位址資訊大於 ULONG_MAX
ERROR_NOT_ENOUGH_MEMORY
記憶體資源不足,無法完成作業。
ERROR_NO_DATA
找不到所要求參數的位址。
其他
使用 FormatMessage 取得傳回錯誤的訊息字串。

備註


GetAdaptersAddresses 函式可以擷取 IPv4 和 IPv6 位址的資訊。

位址會以AdapterAddresses參數所指向之緩衝區中IP_ADAPTER_ADDRESSES結構的連結清單傳回。 呼叫GetAdaptersAddresses函式的應用程式必須配置傳回AdapterAddresses參數所指向之IP_ADAPTER_ADDRESSES結構所需的記憶體數量。 不再需要這些傳回的結構時,應用程式應該釋放配置的記憶體。 這可以藉由呼叫 HeapAlloc 函式來配置記憶體,稍後呼叫 HeapFree 函式以釋放配置的記憶體來完成,如範例程式碼所示。 只要配置和可用函式都使用相同的函式系列,即可使用其他記憶體配置和可用函式。

GetAdaptersAddresses 只會實作為同步函式呼叫。 GetAdaptersAddresses函式需要大量的網路資源和完成時間,因為必須周遊所有低階網路介面資料表。

一個可用來判斷傳回AdapterAddresses參數所指向之IP_ADAPTER_ADDRESSES結構所需記憶體的方法,就是傳遞太小的緩衝區大小,如GetAdaptersAddresses 函式第一次呼叫 GetAdaptersAddresses函式中所指出的SizePointer參數中所述,因此函式會失敗並ERROR_BUFFER_OVERFLOW。 當傳回值 ERROR_BUFFER_OVERFLOW時, 傳回的 SizePointer 參數會指向所需的緩衝區大小,以保存配接器資訊。 請注意,如果新增或移除配接器位址,則 AdapterAddresses參數所指向之IP_ADAPTER_ADDRESSES結構所需的緩衝區大小,可以在後續呼叫 GetAdaptersAddresses函式之間變更。 不過,強烈建議您不要使用 GetAdaptersAddresses 函式的這個方法。 這個方法需要多次呼叫 GetAdaptersAddresses 函 式。

呼叫 GetAdaptersAddresses 函式的建議方法是預先配置 AdapterAddresses 參數所指向的 15KB 工作緩衝區。 在一般電腦上,這可大幅減少 GetAdaptersAddresses 函式傳回 ERROR_BUFFER_OVERFLOW的機會,這需要多次呼叫 GetAdaptersAddresses 函式。 此範例程式碼說明這個使用方法。

在Windows 10之前的版本中,此函式所傳回清單中顯示介面卡的順序可以從 [網路連線] 資料夾控制:從 [進階] 功能表中選取 [進階設定] 功能表項目。 從Windows 10開始,配接器出現在清單中的順序取決於 IPv4 或 IPv6 路由計量。

如果已設定GAA_FLAG_INCLUDE_ALL_INTERFACES,則會擷取所有 NDIS 介面卡,即使這些位址與未系結至 Family 參數中指定的位址系列相關聯也一樣。 如果未設定此旗標,則只會傳回針對 Family 參數中指定的位址系列所系結至介面卡的位址。

IP_ADAPTER_ADDRESSES 結構的大小 已在 Windows XP 上變更,Service Pack 1 (SP1) 和更新版本。 已將數個額外的成員新增至這個結構。 Windows Vista 和更新版本上也變更 了IP_ADAPTER_ADDRESSES 結構的大小。 已將此結構新增一些額外的成員。 IP_ADAPTER_ADDRESSES 結構的大小 也會在 Windows Vista 上變更,Service Pack 1 (SP1) 和更新版本,以及 Windows Server 2008 和更新版本。 此結構中新增了一個額外的成員。 AdapterAddresses參數所指向之緩衝區中結構連結清單中傳回之IP_ADAPTER_ADDRESSES結構的Length成員,應該用來判斷正在使用哪一個IP_ADAPTER_ADDRESSES結構版本。

GetIpAddrTable函式會擷取本機電腦上的介面對 IPv4 位址對應表,並在MIB_IPADDRTABLE結構中傳回這項資訊。

在針對 Windows Server 2003 和更早版本發行的 Platform Software Development Kit (SDK) 上, GetAdaptersAddresses 函式的傳回值定義為 DWORD,而不是 ULONG

SOCKET_ADDRESS結構用於AdapterAddresses參數所指向的IP_ADAPTER_ADDRESSES結構中。 在針對 Windows Vista 和更新版本發行的 Microsoft Windows 軟體發展工具組 (SDK) 上,標頭檔的組織已變更,且SOCKET_ADDRESS結構定義在Winsock2.h標頭檔自動包含的Ws2def.h標頭檔中。 在 Windows Server 2003 和 Windows XP 發行的平臺 SDK 上, SOCKET_ADDRESS 結構會在 Winsock2.h 標頭檔中宣告。 若要使用IP_ADAPTER_ADDRESSES結構,必須在Iphlpapi.h標頭檔之前包含Winsock2.h標頭檔。

範例

此範例會擷取與系統相關聯之介面卡 的IP_ADAPTER_ADDRESSES 結構,並列印每個介面卡介面的一些成員。

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>

// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")

#define WORKING_BUFFER_SIZE 15000
#define MAX_TRIES 3

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

/* Note: could also use malloc() and free() */

int __cdecl main(int argc, char **argv)
{

    /* Declare and initialize variables */

    DWORD dwRetVal = 0;

    unsigned int i = 0;

    // Set the flags to pass to GetAdaptersAddresses
    ULONG flags = GAA_FLAG_INCLUDE_PREFIX;

    // default to unspecified address family (both)
    ULONG family = AF_UNSPEC;

    LPVOID lpMsgBuf = NULL;

    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    ULONG outBufLen = 0;
    ULONG Iterations = 0;

    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
    PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
    PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
    PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
    IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
    IP_ADAPTER_PREFIX *pPrefix = NULL;

    if (argc != 2) {
        printf(" Usage: getadapteraddresses family\n");
        printf("        getadapteraddresses 4 (for IPv4)\n");
        printf("        getadapteraddresses 6 (for IPv6)\n");
        printf("        getadapteraddresses A (for both IPv4 and IPv6)\n");
        exit(1);
    }

    if (atoi(argv[1]) == 4)
        family = AF_INET;
    else if (atoi(argv[1]) == 6)
        family = AF_INET6;

    printf("Calling GetAdaptersAddresses function with family = ");
    if (family == AF_INET)
        printf("AF_INET\n");
    if (family == AF_INET6)
        printf("AF_INET6\n");
    if (family == AF_UNSPEC)
        printf("AF_UNSPEC\n\n");

    // Allocate a 15 KB buffer to start with.
    outBufLen = WORKING_BUFFER_SIZE;

    do {

        pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
        if (pAddresses == NULL) {
            printf
                ("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
            exit(1);
        }

        dwRetVal =
            GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);

        if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
            FREE(pAddresses);
            pAddresses = NULL;
        } else {
            break;
        }

        Iterations++;

    } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));

    if (dwRetVal == NO_ERROR) {
        // If successful, output some information from the data we received
        pCurrAddresses = pAddresses;
        while (pCurrAddresses) {
            printf("\tLength of the IP_ADAPTER_ADDRESS struct: %ld\n",
                   pCurrAddresses->Length);
            printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex);
            printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName);

            pUnicast = pCurrAddresses->FirstUnicastAddress;
            if (pUnicast != NULL) {
                for (i = 0; pUnicast != NULL; i++)
                    pUnicast = pUnicast->Next;
                printf("\tNumber of Unicast Addresses: %d\n", i);
            } else
                printf("\tNo Unicast Addresses\n");

            pAnycast = pCurrAddresses->FirstAnycastAddress;
            if (pAnycast) {
                for (i = 0; pAnycast != NULL; i++)
                    pAnycast = pAnycast->Next;
                printf("\tNumber of Anycast Addresses: %d\n", i);
            } else
                printf("\tNo Anycast Addresses\n");

            pMulticast = pCurrAddresses->FirstMulticastAddress;
            if (pMulticast) {
                for (i = 0; pMulticast != NULL; i++)
                    pMulticast = pMulticast->Next;
                printf("\tNumber of Multicast Addresses: %d\n", i);
            } else
                printf("\tNo Multicast Addresses\n");

            pDnServer = pCurrAddresses->FirstDnsServerAddress;
            if (pDnServer) {
                for (i = 0; pDnServer != NULL; i++)
                    pDnServer = pDnServer->Next;
                printf("\tNumber of DNS Server Addresses: %d\n", i);
            } else
                printf("\tNo DNS Server Addresses\n");

            printf("\tDNS Suffix: %wS\n", pCurrAddresses->DnsSuffix);
            printf("\tDescription: %wS\n", pCurrAddresses->Description);
            printf("\tFriendly name: %wS\n", pCurrAddresses->FriendlyName);

            if (pCurrAddresses->PhysicalAddressLength != 0) {
                printf("\tPhysical address: ");
                for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength;
                     i++) {
                    if (i == (pCurrAddresses->PhysicalAddressLength - 1))
                        printf("%.2X\n",
                               (int) pCurrAddresses->PhysicalAddress[i]);
                    else
                        printf("%.2X-",
                               (int) pCurrAddresses->PhysicalAddress[i]);
                }
            }
            printf("\tFlags: %ld\n", pCurrAddresses->Flags);
            printf("\tMtu: %lu\n", pCurrAddresses->Mtu);
            printf("\tIfType: %ld\n", pCurrAddresses->IfType);
            printf("\tOperStatus: %ld\n", pCurrAddresses->OperStatus);
            printf("\tIpv6IfIndex (IPv6 interface): %u\n",
                   pCurrAddresses->Ipv6IfIndex);
            printf("\tZoneIndices (hex): ");
            for (i = 0; i < 16; i++)
                printf("%lx ", pCurrAddresses->ZoneIndices[i]);
            printf("\n");

            printf("\tTransmit link speed: %I64u\n", pCurrAddresses->TransmitLinkSpeed);
            printf("\tReceive link speed: %I64u\n", pCurrAddresses->ReceiveLinkSpeed);

            pPrefix = pCurrAddresses->FirstPrefix;
            if (pPrefix) {
                for (i = 0; pPrefix != NULL; i++)
                    pPrefix = pPrefix->Next;
                printf("\tNumber of IP Adapter Prefix entries: %d\n", i);
            } else
                printf("\tNumber of IP Adapter Prefix entries: 0\n");

            printf("\n");

            pCurrAddresses = pCurrAddresses->Next;
        }
    } else {
        printf("Call to GetAdaptersAddresses failed with error: %d\n",
               dwRetVal);
        if (dwRetVal == ERROR_NO_DATA)
            printf("\tNo addresses were found for the requested parameters\n");
        else {

            if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
                    NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),   
                    // Default language
                    (LPTSTR) & lpMsgBuf, 0, NULL)) {
                printf("\tError: %s", lpMsgBuf);
                LocalFree(lpMsgBuf);
                if (pAddresses)
                    FREE(pAddresses);
                exit(1);
            }
        }
    }

    if (pAddresses) {
        FREE(pAddresses);
    }

    return 0;
}

需求

   
最低支援的用戶端 Windows XP [傳統型應用程式 |UWP 應用程式]
最低支援的伺服器 Windows Server 2003 [傳統型應用程式 |UWP 應用程式]
目標平台 Windows
標頭 iphlpapi.h
程式庫 Iphlpapi.lib
Dll Iphlpapi.dll

另請參閱

GetIpAddrTable

HeapAlloc

HeapFree

IP 協助程式函式參考

IP 協助程式起始頁

IP_ADAPTER_ADDRESSES

MIB_IPADDRTABLE

SOCKET_ADDRESS

Windows Sockets