GetAdaptersInfo()
和GetAdaptersAddresses()
都報告每個網絡適配器的本地IP和網關。例如:
uses
..., IpTypes, IpHlpApi;
procedure GetLocalAddressesByAdaptersAddresses;
var
Ret: DWORD;
BufLen: ULONG;
Adapter, Adapters: PIP_ADAPTER_ADDRESSES;
UnicastAddr: PIP_ADAPTER_UNICAST_ADDRESS;
Gateway: PIP_ADAPTER_GATEWAY_ADDRESS;
IPAddr: string;
begin
// MSDN says:
// The recommended method of calling the GetAdaptersAddresses function is
// to pre-allocate a 15KB working buffer pointed to by the AdapterAddresses
// parameter. On typical computers, this dramatically reduces the chances
// that the GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW,
// which would require calling GetAdaptersAddresses function multiple times.
BufLen := 1024*15;
GetMem(Adapters, BufLen);
try
repeat
// TODO: include GAA_FLAG_INCLUDE_ALL_INTERFACES on Vista+?
Ret := GetAdaptersAddresses(PF_UNSPEC, GAA_FLAG_SKIP_ANYCAST or GAA_FLAG_SKIP_MULTICAST or GAA_FLAG_SKIP_DNS_SERVER or GAA_FLAG_SKIP_FRIENDLY_NAME or GAA_FLAG_INCLUDE_GATEWAYS, nil, Adapters, BufLen);
case Ret of
ERROR_SUCCESS:
begin
// Windows CE versions earlier than 4.1 may return ERROR_SUCCESS and
// BufLen=0 if no adapter info is available, instead of returning
// ERROR_NO_DATA as documented...
if BufLen = 0 then begin
Exit;
end;
Break;
end;
ERROR_NOT_SUPPORTED:
begin
Result := False;
Exit;
end;
ERROR_NO_DATA,
ERROR_ADDRESS_NOT_ASSOCIATED:
Exit;
ERROR_BUFFER_OVERFLOW:
ReallocMem(Adapters, BufLen);
else
RaiseLastError(Ret);
end;
until False;
if Ret = ERROR_SUCCESS then
begin
Adapter := Adapters;
repeat
if (Adapter.IfType <> IF_TYPE_SOFTWARE_LOOPBACK) and
((Adapter.Flags and IP_ADAPTER_RECEIVE_ONLY) = 0) then
begin
UnicastAddr := Adapter^.FirstUnicastAddress;
while UnicastAddr <> nil do
begin
if UnicastAddr^.DadState = IpDadStatePreferred then
begin
case UnicastAddr^.Address.lpSockaddr.sin_family of
AF_INET: begin
// use PSockAddrIn(UnicastAddr^.Address.lpSockaddr)^.sin_addr as needed...
end;
AF_INET6: begin
// use PSockAddrIn6(UnicastAddr^.Address.lpSockaddr)^.sin6_addr as needed...
end;
end;
end;
UnicastAddr := UnicastAddr^.Next;
end;
Gateway := Adapter^.FirstGatewayAddress;
while Gateway <> nil do
begin
case Gateway^.Address.lpSockaddr.sin_family of
AF_INET: begin
// use PSockAddrIn(Gateway^.Address.lpSockaddr)^.sin_addr as needed...
end;
AF_INET6: begin
// use PSockAddrIn6(Gateway^.Address.lpSockaddr)^.sin6_addr as needed...
end;
end;
Gateway := Gateway^.Next;
end;
end;
Adapter := Adapter^.Next;
until Adapter = nil;
end;
finally
FreeMem(Adapters);
end;
end;
procedure GetLocalAddressesByAdaptersInfo;
var
Ret: DWORD;
BufLen: ULONG;
Adapter, Adapters: PIP_ADAPTER_INFO;
IPAddr, Gateway: PIP_ADDR_STRING;
begin
BufLen := 1024*15;
GetMem(Adapters, BufLen);
try
repeat
Ret := GetAdaptersInfo(Adapters, BufLen);
case Ret of
ERROR_SUCCESS:
begin
// Windows CE versions earlier than 4.1 may return ERROR_SUCCESS and
// BufLen=0 if no adapter info is available, instead of returning
// ERROR_NO_DATA as documented...
if BufLen = 0 then begin
Exit;
end;
Break;
end;
ERROR_NOT_SUPPORTED,
ERROR_NO_DATA:
Exit;
ERROR_BUFFER_OVERFLOW:
ReallocMem(Adapters, BufLen);
else
RaiseLastOSError(Ret);
end;
until False;
if Ret = ERROR_SUCCESS then
begin
Adapter := Adapters;
repeat
IPAddr := @(Adapter^.IpAddressList);
repeat
// use IPAddr^.IpAddress.S as needed...
IPAddr := IPAddr^.Next;
until IPAddr = nil;
Gateway := @(Adapter^.GatewayList);
repeat
// use Gateway^.IpAddress.S as needed...
Gateway := Gateway^.Next;
until Gateway = nil;
Adapter := Adapter^.Next;
until Adapter = nil;
end;
finally
FreeMem(Adapters);
end;
end;
歡迎來到StackOverflow!你可以發佈其中一個鏈接到MS網站,你發現有幫助,以便我們知道你已經在看什麼? – nmagerko 2014-10-01 21:22:31
您爲每個連接的網絡適配器安裝了IP地址。使用VMWare,您至少可以獲得兩個(一個用於橋接虛擬機,另一個用於NAT)。我記得幾年前和WMI一起玩Windows的那種信息,但我再也無法訪問這些代碼。 – 2014-10-01 21:31:40
如果你想調用Win API函數,你需要能夠閱讀和理解文檔。它不會幫助其他人爲你做所有的工作,因爲你不準備學習如何使用這個文檔。你需要調整你的期望。 – 2014-10-02 06:26:45