Я смотрю на простые решения в Lazarus / FPC, чтобы получить локальный IP-адрес, и, конечно, INDY кажется самым простым. Это на виртуальной машине MacOS Parallels, на которой запущена Mojave с MBP 2015. Я использую Lazarus 2.0.0RC3 и код в DYLIB. Мне нужен IP-адрес локального компьютера, чтобы получить его MAC-адрес.
Я использую TIdWatch
, который должен просто возвращать локальный IP-адрес (из его свойства CurrentIP
). Мне нравятся оба решения, подробно описанные ниже IdStack
, потому что код очень прост, но, конечно, независимо от того, насколько он прост, он не принесет пользы, если код не работает:
uses
IdBaseComponent,
IdComponent,
IdIPWatch,
...
function getLocalIP: string;
var
IPW: TIdIPWatch;
begin
IpW := TIdIPWatch.Create(nil);
try
if IpW.LocalIP <> '' then
Result := IpW.LocalIP;
ShowMessage('IP: ' + Result);
finally
IpW.Free;
end;
end;
Фактический IP-адрес - 192.168.1.25, но вызов IdPWatch.LocalIP
возвращает пустую строку.
Я попытался установить Active
в True (IpW.Active := True;
), но это просто убивает приложение (я не уверен, почему, оно просто внезапно завершается).
Аналогично, я попытался использовать IdStack
и получил ту же проблему, т.е. Возвращает пустую строку:
uses
IdStack,
...
function GetLocalIP : String;
begin
TIdStack.IncUsage;
try
Result := GStack.LocalAddress;
ShowMessage('IP: ' + Result);
finally
TIdStack.DecUsage;
end;
end;
Опять же, этот код был из Интернета, но я просмотрел документацию для IdStack
и TIdIPWatch
, и, согласно моим прочтениям, должен вернуть локальный IP-адрес, указанный на веб-сайте Lazarus.
EDIT:
Согласно комментарию Реми, я исправил функцию, чтобы использовать функцию GStack.GetLocalAddressList вместо устаревших функций, которые я ранее использовал. Обратите внимание, что результат тот же, и что IPList (переменная TIdStackLocalAddressList) не имеет элементов:
function getLocalIP: string;
var
IPList: TIdStackLocalAddressList;
IPStrings: TStringList;
i: integer;
begin
try
try
Result:='';
IPList:=TIdStackLocalAddressList.Create;
IPStrings := TStringList.create;
TIdStack.IncUsage;
GStack.GetLocalAddressList(IPList);
if IPList.count > 0 then
begin
WriteLog('DEBUG', 'No of Addresses: ' + inttostr(IPList.count));
for i := 0 to IPList.Count - 1 do
begin
if IPList[i].IPVersion = Id_IPv4 then
begin
IPStrings.Add(IPList[i].IPAddress+':'+ TIdStackLocalAddressIPv4(IPList[i]).SubNetMask);
end;
end;
// show IP Addresses in the log file
if IPStrings.Count > 0 then
begin
for i := 0 to IPStrings.Count -1 do
WriteLog('DEBUG', 'IP Address #' + inttostr(i) + ': ' + IPStrings[i]);
Result := IPStrings[0];
WriteLog('DEBUG', 'IP: ' + Result);
end
else
WriteLog('DEBUG', 'IPStrings has no entries');
end
else
WriteLog('DEBUG', 'TIdStackLocalAddressList has no entries');
except
On E:Exception do
begin
Result := '';
WriteLog('ERROR', 'IP Error: ' + E.message);
end;
end;
finally
TIdStack.DecUsage;
end;
end;
Итак, мои вопросы:
Можно ли использовать TIdIPWatch
или TIdStack
в Lazarus / FPC для поиска локального IP-адреса виртуальной машины?
Может ли кто-нибудь увидеть какие-либо явные ошибки в фрагментах кода, которые я разместил, которые препятствуют возвращению локального IP-адреса?
Я рад опубликовать больше кода и ответить на любые вопросы, если вы чувствуете, что я что-то пропустил.
EDIT2:
Таким образом, и INDY, и другие методы настроены на использование ifconfig для получения IP-адреса. Решения, похоже, ищут «net Add:»
В MacOS Mojave 10.14 IfConfig не возвращает 'net Addr:'. Он просто возвращает net, по крайней мере, в моей виртуальной машине Parallels. Вы можете изменить код соответствующим образом. Обратите внимание, что выходные данные виртуальной машины и физической системы выглядят по-разному:
Типичный вывод из моей системы Mojave Parallels VM (<> заполняет цитату блока):
kevin$ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
UHC29: flags=0<> mtu 0
EHC253: flags=0<> mtu 0
XHC221: flags=0<> mtu 0
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=2b<RXCSUM,TXCSUM,VLAN_HWTAGGING,TSO4>
ether 00:1c:42:72:74:a3
inet6 fe80::3a:650d:9b24:c9c5%en0 prefixlen 64 secured scopeid 0x7
inet 192.168.1.25 netmask 0xffffff00 broadcast 192.168.1.255
nd6 options=201<PERFORMNUD,DAD>
media: autoselect (1000baseT <full-duplex>)
Типичный вывод из жестких систем, работающих под управлением Mojave (фактический IP-адрес - en0 (5), сетевой адрес):
kevin$ ifconfig
awdl0 (8):
flags UP BROADCAST RUNNING PROMISC SIMPLEX MULTICAST
mtu 1484
bridge0 (10):
flags UP BROADCAST NOTRAILERS RUNNING SIMPLEX MULTICAST
mtu 1500
en0 (5):
inet address 192.168.1.167
netmask 255.255.255.0
broadcast 192.168.1.255
flags UP BROADCAST NOTRAILERS RUNNING PROMISC SIMPLEX MULTICAST
mtu 1500
en1 (7):
flags UP BROADCAST NOTRAILERS RUNNING PROMISC SIMPLEX MULTICAST
mtu 1500
en2 (9):
flags UP BROADCAST NOTRAILERS RUNNING PROMISC SIMPLEX MULTICAST
mtu 1500
lo0 (1):
inet address 127.0.0.1
netmask 255.0.0.0
flags UP LOOPBACK RUNNING MULTICAST
mtu 16384
p2p0 (6):
flags UP BROADCAST RUNNING SIMPLEX MULTICAST
mtu 2304
utun0 (11):
flags UP POINTOPOINT RUNNING MULTICAST
mtu 2000
utun1 (12):
flags UP POINTOPOINT RUNNING MULTICAST
mtu 1380
vnic0 (13):
inet address 10.211.55.2
netmask 255.255.255.0
broadcast 10.211.55.255
flags UP BROADCAST RUNNING SIMPLEX MULTICAST
mtu 1500
vnic1 (14):
inet address 10.37.129.2
netmask 255.255.255.0
broadcast 10.37.129.255
flags UP BROADCAST RUNNING SIMPLEX MULTICAST
mtu 1500
В чем суть, ну это сбивает с толку. На виртуальной машине вам нужно искать «inet», а на жесткой системе - «inet address». Теперь я первый, кто признает «не врач», это не моя область знаний. Поэтому я не уверен, что INDY 10 ищет «inet:» и / или «inet address:» с двоеточием в конце. Если это так, это объясняет, почему это не работает. Я буду дальше расследовать.