get local IP address / GetLocalIPs compilation error lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- new2linux · 2014-05-07 13:47 I am trying to get the local IP address. I am already using synapse and saw it contains the GetLocalIPs function in unit synamisc. However, when I try to use it, upon including synamisc, lots of error crop up (see below), which suggest to me it is trying to use the LCL. What surprises me is that I have included units httpsend, synacode, synautil and ssl_openssl without this occurring. So why would a "misc" unit, as "synamisc" obviously is, have different requirements. Needless to say I am lost. Looking forward to a solution. The errors (lazarus marks them at the begin stmt of the program): gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterCustomImageList gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterMenuItem gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterMenu gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterMainMenu gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterPopupMenu gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterDragImageList gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterLazAccessibleObject gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterControl gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterWinControl gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterGraphicControl gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterCustomControl gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterScrollingWinControl gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterScrollBox gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterCustomFrame gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterCustomForm gwsEnvio.lpr(197,1) Error: Undefined symbol: WSRegisterHintWindow gwsEnvio.lpr(197,1) Fatal: There were 16 errors compiling module, stopping ---------------------------------------------------------------------- jwdietrich · 2014-05-07 13:50 Please provide information about your platform, OS and Lazarus version. ---------------------------------------------------------------------- new2linux · 2014-05-09 20:07 OS: Windows 8.1 with and without update. Lazarus: version 1.2.2 ---------------------------------------------------------------------- Jurassic Pork · 2014-05-09 23:38 hello, you can try to recreate your own GetLocalIPs  function : Code: [Select]uses ...., blcksock; function  MyGetLocalIPs: string; var   TcpSock: TTCPBlockSocket;   ipList: TStringList; begin   Result := '';   ipList := TStringList.Create;   try     TcpSock := TTCPBlockSocket.create;     try       TcpSock.ResolveNameToIP(TcpSock.LocalName, ipList);       Result := ipList.CommaText;     finally       TcpSock.Free;     end;   finally     ipList.Free;   end; end; Friendly, J.P ---------------------------------------------------------------------- taazz · 2014-05-10 00:04 not enough information please create a small demo that shows the problem and attach it here. I tried to use the synamisc on a clean application created with lazarus 1.2.0 and I see no such messages. There are a couple of possibilities eg, there is a regression on 1.2.2 that creates the problem, you have an different version of synapse installed I created a new application when I should have created a new program instead. ---------------------------------------------------------------------- new2linux · 2014-05-12 12:43 I have tracked down the problem. In trying to fork some common code way down to the basics of the app, a dependency on TApplication was created deep down, which inadvertently introduced the Forms unit, whereas I use a console mode. All errors result from including that unit in another unit. Shame on me @Jurassic Pork: I have tracked down a lot of examples to get the local IP, but your code is vastly superior in its simplicity and exactly what I was looking for   Thanks man. Thanks everyone for being so helpful. ---------------------------------------------------------------------- calebs · 2014-10-21 22:43 Quote from: Jurassic Pork on May 10, 2014, 01:38:23 amhello, you can try to recreate your own GetLocalIPs  function : Code: [Select]uses ...., blcksock; function  MyGetLocalIPs: string; var   TcpSock: TTCPBlockSocket;   ipList: TStringList; begin   Result := '';   ipList := TStringList.Create;   try     TcpSock := TTCPBlockSocket.create;     try       TcpSock.ResolveNameToIP(TcpSock.LocalName, ipList);       Result := ipList.CommaText;     finally       TcpSock.Free;     end;   finally     ipList.Free;   end; end; Friendly, J.P Hello jurassicpork i've used your code but i had to make a simple modification because in windows i get first the IPV6 and it was useless to me and filter the localhost. The problem is in linux. It only gives me 127.0.1.1 (it is not even the loopback). I've checked with ifconfig and i have correct ip local configuration (ie: 10.0.0.113) but never get that ip. Any hint? Code: [Select]function devolverip : string; var   TcpSock: TTCPBlockSocket;   ipList: TStringList;   cont: Integer;   enc: Boolean;   cad: String; begin   Result := '';   ipList := TStringList.Create;   try     TcpSock := TTCPBlockSocket.create;     try       TcpSock.ResolveNameToIP(TcpSock.LocalName, ipList);       cont:=0;       enc := false;       repeat         cad:=UpperCase(iplist[cont]);         if pos('127.0.',cad)>0 then begin           inc(cont);           continue;         end;         if (pos('E', cad)>0) or (pos('A', cad)>0) or (pos('B', cad)>0) or (pos('C', cad)>0) or (pos('D', cad)>0)  or (pos('F', cad)>0) then begin           inc(cont);           continue;         end;         enc:=true;         inc(cont);       until cont>=iplist.Count-1;       if enc then         result:=cad       else         result:='Indef';     finally       TcpSock.Free;     end;   finally     ipList.Free;   end; end; ---------------------------------------------------------------------- Jurassic Pork · 2014-10-23 02:13 hello, under linux you can use runcommand to run ifconfig and regexpr to parse result.  for example to extract mac and ip address of the eth0 interface : Code: [Select]uses  Regexpr,Process, .... .... var reponse : string;     re: TRegExpr;     i: integer; begin RunCommand('/sbin/ifconfig',['eth0'],reponse); try   re := TRegExpr.Create;   re.Expression := 'HWaddr ([^ ]+).*inet adr:([^ ]+)';   re.Exec(reponse);   for i:=1 to re.SubExprMatchCount do     writeln(re.Match[i]); finally   re.Free; end;        end; Friendly, J.P ps : runcommand available since fpc 2.6.4  ( see fpc\2.6.4\source\packages\fcl-process\src\process.pp) ---------------------------------------------------------------------- dogriz · 2014-10-23 06:20 Quote from: Jurassic Pork on October 23, 2014, 04:13:01 amhello, under linux you can use runcommand to run ifconfig and regexpr to parse result.  Don't you need root privileges for that? ---------------------------------------------------------------------- eric · 2014-10-23 12:14 Quote from: dogriz on October 23, 2014, 08:20:05 amQuote from: Jurassic Pork on October 23, 2014, 04:13:01 amhello, under linux you can use runcommand to run ifconfig and regexpr to parse result.  Don't you need root privileges for that? Not if you only want to read information. You have to give the full pathname /sbin/ifconfig because /sbin isn't usually in the normal user's path. ---------------------------------------------------------------------- calebs · 2014-10-24 14:33 Quote from: Jurassic Pork on October 23, 2014, 04:13:01 amhello, under linux you can use runcommand to run ifconfig and regexpr to parse result.  for example to extract mac and ip address of the eth0 interface : Code: [Select]uses  Regexpr,Process, .... .... var reponse : string;     re: TRegExpr;     i: integer; begin RunCommand('/sbin/ifconfig',['eth0'],reponse); try   re := TRegExpr.Create;   re.Expression := 'HWaddr ([^ ]+).*inet adr:([^ ]+)';   re.Exec(reponse);   for i:=1 to re.SubExprMatchCount do     writeln(re.Match[i]); finally   re.Free; end;        end; Friendly, J.P ps : runcommand available since fpc 2.6.4  ( see fpc\2.6.4\source\packages\fcl-process\src\process.pp) Thanks jurassic i think then that i have to make a function using directives to ask if is it windows or linux to get the ip's. In windows i've found i can use synapse or winsock i guess. Thanks! ---------------------------------------------------------------------- mirce.vladimirov · 2014-10-24 15:57 Quote from: calebs on October 24, 2014, 04:33:10 pmThanks jurassic i think then that i have to make a function using directives to ask if is it windows or linux to get the ip's. In windows i've found i can use synapse or winsock i guess. Thanks! Here you can read about OS detection under Lazarus. http://forum.lazarus.freepascal.org/index.php?topic=15390.0 ---------------------------------------------------------------------- serbod · 2014-10-24 17:29 I using this function on Linux and Windows (tested on XP, Embedded, 7) Code: [Select]function GetIpAddrList(): string; var   AProcess: TProcess;   s: string;   sl: TStringList;   i, n: integer; begin   Result:='';   sl:=TStringList.Create();   {$IFDEF WINDOWS}   AProcess:=TProcess.Create(nil);   AProcess.CommandLine := 'ipconfig.exe';   AProcess.Options := AProcess.Options + [poUsePipes, poNoConsole];   try     AProcess.Execute();     Sleep(500); // poWaitOnExit not working as expected     sl.LoadFromStream(AProcess.Output);   finally     AProcess.Free();   end;   for i:=0 to sl.Count-1 do   begin     if (Pos('IPv4', sl[i])=0) and (Pos('IP-', sl[i])=0) and (Pos('IP Address', sl[i])=0) then Continue;     s:=sl[i];     s:=Trim(Copy(s, Pos(':', s)+1, 999));     if Pos(':', s)>0 then Continue; // IPv6     Result:=Result+s+'  ';   end;   {$ENDIF}   {$IFDEF UNIX}   AProcess:=TProcess.Create(nil);   AProcess.CommandLine := '/sbin/ifconfig';   AProcess.Options := AProcess.Options + [poUsePipes, poWaitOnExit];   try     AProcess.Execute();     //Sleep(500); // poWaitOnExit not working as expected     sl.LoadFromStream(AProcess.Output);   finally     AProcess.Free();   end;   for i:=0 to sl.Count-1 do   begin     n:=Pos('inet addr:', sl[i]);     if n=0 then Continue;     s:=sl[i];     s:=Copy(s, n+Length('inet addr:'), 999);     Result:=Result+Trim(Copy(s, 1, Pos(' ', s)))+'  ';   end;   {$ENDIF}   sl.Free(); end; ---------------------------------------------------------------------- calebs · 2014-10-28 20:29 Thanks serbod i'll try and i'll tell you if it works for me ---------------------------------------------------------------------- calebs · 2014-11-10 19:56 Finally worked. The only problem is to find wich of the Ip's that returns is main but it's not trouble for now. I'll share the code here, i've modified the linux part to work in spanish linux, i guess it must be changed for other languages to. Thanks Code: [Select]function devolverip : string; //function GetIpAddrList(): string; var   AProcess: TProcess;   s, cad: string;   sl: TStringList;   i, n: integer; begin   Result:='';   sl:=TStringList.Create();   {$IFDEF WINDOWS}   AProcess:=TProcess.Create(nil);   AProcess.CommandLine := 'ipconfig.exe';   AProcess.Options := AProcess.Options + [poUsePipes, poNoConsole];   try     AProcess.Execute();     Sleep(500); // poWaitOnExit not working as expected     sl.LoadFromStream(AProcess.Output);   finally     AProcess.Free();   end;   for i:=0 to sl.Count-1 do   begin     if (Pos('IPv4', sl[i])=0) and (Pos('IP-', sl[i])=0) and (Pos('IP Address', sl[i])=0) then Continue;     s:=sl[i];     s:=Trim(Copy(s, Pos(':', s)+1, 999));     if Pos(':', s)>0 then Continue; // IPv6     Result:=Result+s+'  ';   end;   {$ENDIF}   {$IFDEF UNIX}   AProcess:=TProcess.Create(nil);   AProcess.CommandLine := '/sbin/ifconfig';   AProcess.Options := AProcess.Options + [poUsePipes, poWaitOnExit];   try     AProcess.Execute();     //Sleep(500); // poWaitOnExit not working as expected     sl.LoadFromStream(AProcess.Output);   finally     AProcess.Free();   end;   for i:=0 to sl.Count-1 do   begin     cad:='inet addr:';     n:=Pos(cad, sl[i]);     if n=0 then begin       cad:='Direc. inet:';       n:=Pos(cad, sl[i]);     end;     if n=0 then begin       cad:='inet:';       n:=Pos(cad, sl[i]);     end;     if n=0 then       Continue;     s:=sl[i];     s:=Copy(s, n+Length(cad), 999);     Result:=Result+Trim(Copy(s, 1, Pos(' ', s)))+'  ';   end;   {$ENDIF}   sl.Free(); end; ---------------------------------------------------------------------- elidorio · 2015-05-14 03:15 This function is not working with linux! Does anyone have something that works with linux?