If I add Interfaces to the main unit the project compiles fine. But is
it ok to add interfaces to a console application?
I need two LCL unit, LCLtype and LCLintf. I use this unit in order to
get the mac address on windows (using netapi32.dll).
I found a delphi code and I modified it in order to run it on lazarus,
but I didn't understand everything, I only know that actually it works.
Here the code:
{ *********************************************************************** }
{ }
{ Unit containing NetBIOS 3.0 definition }
{ Porting of Nb30 Delphi unit to FreePascal }
{ And GetLoginName Function }
{ }
{ }
{ *********************************************************************** }
unit my_sysinfo;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils
{$IFDEF MSWINDOWS}
, snmp, nb30, dynlibs, LCLtype, LCLintf, LCLProc
{$ENDIF MSWINDOWS}
{$IFDEF LINUX}
, baseunix, sockets, users
{$ENDIF};
type
TUser = record
Name: string; { Username. }
Passwd: string; { Password. }
User_id: Cardinal; { User ID. }
Group_id: Cardinal; { Group ID. }
Real_name: string; { Real name. }
Home_dir: string; { Home directory. }
Shell: string; { Shell program. }
end;
function GetMACAddress: string;
function GetUserInfo: TUser;
implementation
{$IFDEF LINUX}
const
IF_NAMESIZE = 16;
SIOCGIFCONF = $8912;
SIOCGIFHWADDR = $8927;
type
{$packrecords c}
tifr_ifrn = record
case integer of
0 : (ifrn_name: array [0..IF_NAMESIZE-1] of char);
end;
tifmap = record
mem_start : cardinal;
mem_end : cardinal;
base_addr : word;
irq : byte;
dma : byte;
port : byte;
end;
PIFrec = ^TIFrec;
TIFrec = record
ifr_ifrn : tifr_ifrn;
case integer of
0 : (ifru_addr : TSockAddr);
1 : (ifru_dstaddr : TSockAddr);
2 : (ifru_broadaddr : TSockAddr);
3 : (ifru_netmask : TSockAddr);
4 : (ifru_hwaddr : TSockAddr);
5 : (ifru_flags : word);
6 : (ifru_ivalue : longint);
7 : (ifru_mtu : longint);
8 : (ifru_map : tifmap);
9 : (ifru_slave : Array[0..IF_NAMESIZE-1] of char);
10 : (ifru_newname : Array[0..IF_NAMESIZE-1] of char);
11 : (ifru_data : pointer);
end;
TIFConf = record
ifc_len : longint;
case integer of
0 : (ifcu_buf : pointer);
1 : (ifcu_req : ^tifrec);
end;
function GetUserInfo: TUser;
var
Data: TPasswordRecord;
begin
GetUserData(FpGetuid, Data);
Result.Name:= Data.pw_name;
Result.Real_name:= Data.pw_gecos;
Result.User_id:= Data.pw_uid;
Result.Group_id:= Data.pw_gid;
Result.home_dir:= Data.pw_dir;
Result.shell:= Data.pw_shell;
end;
(* Taken and modified from macuuid unit in packages/uuid/src/macuuid.pp *)
function GetMACAddress : string;
var
MacAddr: Packed Array[1..6] of byte = (0,0,0,0,0,0);
i,n,Sd : Integer;
buf : Array[0..1023] of byte;
ifc : TIfConf;
ifr : TIFRec;
ifp : PIFRec;
p : PChar;
MACaddress: string;
Found: boolean;
begin
Found:= False;
Result:= '';
sd:=fpSocket(AF_INET,SOCK_DGRAM,IPPROTO_IP);
if (sd<0) then
exit;
Try
ifc.ifc_len:=Sizeof(Buf);
ifc.ifcu_buf:=...@buf;
if fpioctl(sd, SIOCGIFCONF, @ifc)<0 then
Exit;
n:= ifc.ifc_len;
i:=0;
While (Not Found) and (I<N) do
begin
ifp:=PIFRec(PByte(ifc.ifcu_buf)+i);
move(ifp^.ifr_ifrn.ifrn_name,ifr.ifr_ifrn.ifrn_name,IF_NAMESIZE);
StrPLCopy(ifr.ifr_ifrn.ifrn_name, 'eth0', IF_NAMESIZE);
if (fpioctl(sd, SIOCGIFHWADDR, @ifr) >= 0) then
begin
P:=Pchar(@ifr.ifru_hwaddr.sa_data);
Found:=(p[0]<>#0) or (p[1]<>#0) or (p[2]<>#0)
or (p[3]<>#0) or (p[4]<>#0) or (p[5]<>#0);
If Found Then
begin
Move(P^,MacAddr,SizeOf(MacAddr));
end;
end;
I:=I+sizeof(tifrec);
end;
Finally
fileClose(sd);
MACaddress:= '';
For i:=1 to 5 do
MACaddress:= MACaddress + hexstr(MacAddr[i],2) + ':';
Result:= MACaddress + hexstr(MacAddr[6],2);
end;
end;
{$ENDIF}
{$IFDEF MSWINDOWS}
type
TNetBios = function(P: PNCB): Byte; stdcall;
var
NetBiosLib: HINST = 0;
_NetBios: TNetBios;
function AdapterToString(Adapter: PByteArray): string;
begin
Result := Format('%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x',
[Adapter^[0], Adapter^[1],
Adapter^[2], Adapter^[3],
Adapter^[4], Adapter^[5]]);
end;
function GetMacAddresses(const Machine: string; const Addresses:
TStringList): Integer;
procedure ExitNetbios;
begin
if NetBiosLib <> 0 then
begin
FreeLibrary(NetBiosLib);
NetBiosLib := 0;
end;
end;
function InitNetbios: Boolean;
begin
Result := True;
if NetBiosLib = 0 then
begin
NetBiosLib := LoadLibrary(PChar('netapi32.dll'));
Result := NetBiosLib <> 0;
if Result then
begin
_NetBios := TNetBios(GetProcAddress(NetBiosLib, PChar('Netbios')));
Result := @_NetBios <> nil;
if not Result then
ExitNetbios;
end;
end;
end;
function NetBios(P: PNCB): Byte;
begin
if InitNetbios then
Result := _NetBios(P)
else
Result := 1; // anything other than NRC_GOODRET will do
end;
procedure GetMacAddressesNetBios;
// Platform SDK
//
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netbios/netbios_1l82.asp
// Microsoft Knowledge Base Article - 118623
// HOWTO: Get the MAC Address for an Ethernet Adapter
// http://support.microsoft.com/default.aspx?scid=kb;en-us;118623
type
AStat = packed record
adapt: TAdapterStatus;
NameBuff: array [0..29] of TNameBuffer;
end;
var
NCB: TNCB;
Enum: TLanaEnum;
I, L, NameLen: Integer;
Adapter: AStat;
MachineName: string;
begin
MachineName := UpperCase(Machine);
if MachineName = '' then
MachineName := '*';
NameLen := Length(MachineName);
L := NCBNAMSZ - NameLen;
if L > 0 then
begin
SetLength(MachineName, NCBNAMSZ);
FillChar(MachineName[NameLen + 1], L, ' ');
end;
FillChar(NCB, SizeOf(NCB), #0);
NCB.ncb_command := Char(NCBENUM);
NCB.ncb_buffer := Pointer(@Enum);
NCB.ncb_length := SizeOf(Enum);
if NetBios(@NCB) = NRC_GOODRET then
begin
Result := Ord(Enum.Length);
for I := 0 to Ord(Enum.Length) - 1 do
begin
FillChar(NCB, SizeOf(NCB), #0);
NCB.ncb_command := Char(NCBRESET);
NCB.ncb_lana_num := Enum.lana[I];
if NetBios(@NCB) = NRC_GOODRET then
begin
FillChar(NCB, SizeOf(NCB), #0);
NCB.ncb_command := Char(NCBASTAT);
NCB.ncb_lana_num := Enum.lana[I];
Move(MachineName[1], NCB.ncb_callname, SizeOf(NCB.ncb_callname));
NCB.ncb_buffer := PChar(@Adapter);
NCB.ncb_length := SizeOf(Adapter);
if NetBios(@NCB) = NRC_GOODRET then
Addresses.Add(AdapterToString(@Adapter.adapt));
end;
end;
end;
end;
procedure GetMacAddressesSnmp;
const
InetMib1 = 'inetmib1.dll';
DunAdapterAddress: array [0..4] of Byte = ($44, $45, $53, $54, $00);
NullAdapterAddress: array [0..5] of Byte = ($00, $00, $00, $00, $00,
$00);
OID_ipMACEntAddr: array [0..9] of UINT = (1, 3, 6, 1, 2, 1, 2, 2, 1, 6);
OID_ifEntryType: array [0..9] of UINT = (1, 3, 6, 1, 2, 1, 2, 2, 1, 3);
OID_ifEntryNum: array [0..7] of UINT = (1, 3, 6, 1, 2, 1, 2, 1);
var
PollForTrapEvent: THandle;
SupportedView: PAsnObjectIdentifier;
MIB_ifMACEntAddr: TAsnObjectIdentifier;
MIB_ifEntryType: TAsnObjectIdentifier;
MIB_ifEntryNum: TAsnObjectIdentifier;
VarBindList: TSnmpVarBindList;
VarBind: array [0..1] of TSnmpVarBind;
ErrorStatus, ErrorIndex: TAsnInteger32;
DTmp: Integer;
Ret: Boolean;
MAC: PByteArray;
begin
if LoadSnmp then
try
if LoadSnmpExtension(InetMib1) then
try
MIB_ifMACEntAddr.idLength := Length(OID_ipMACEntAddr);
MIB_ifMACEntAddr.ids := @OID_ipMACEntAddr;
MIB_ifEntryType.idLength := Length(OID_ifEntryType);
MIB_ifEntryType.ids := @OID_ifEntryType;
MIB_ifEntryNum.idLength := Length(OID_ifEntryNum);
MIB_ifEntryNum.ids := @OID_ifEntryNum;
if SnmpExtensionInit(GetTickCount, PollForTrapEvent,
SupportedView) then
begin
VarBindList.list := @VarBind[0];
VarBind[0].name := DEFINE_NULLOID;
VarBind[1].name := DEFINE_NULLOID;
VarBindList.len := 1;
SnmpUtilOidCpy(@VarBind[0].name, @MIB_ifEntryNum);
Ret := SnmpExtensionQuery(SNMP_PDU_GETNEXT, VarBindList,
ErrorStatus, ErrorIndex);
if Ret then
begin
Result := VarBind[0].value.number;
VarBindList.len := 2;
SnmpUtilOidCpy(@VarBind[0].name, @MIB_ifEntryType);
SnmpUtilOidCpy(@VarBind[1].name, @MIB_ifMACEntAddr);
while Ret do
begin
Ret := SnmpExtensionQuery(SNMP_PDU_GETNEXT, VarBindList,
ErrorStatus, ErrorIndex);
if Ret then
begin
Ret := SnmpUtilOidNCmp(@VarBind[0].name,
@MIB_ifEntryType, MIB_ifEntryType.idLength) = SNMP_ERRORSTATUS_NOERROR;
if Ret then
begin
DTmp := VarBind[0].value.number;
if DTmp = 6 then
begin
Ret := SnmpUtilOidNCmp(@VarBind[1].name,
@MIB_ifMACEntAddr, MIB_ifMACEntAddr.idLength) = SNMP_ERRORSTATUS_NOERROR;
if Ret and (VarBind[1].value.address.stream <> nil) then
begin
MAC := PByteArray(VarBind[1].value.address.stream);
if not CompareMem(MAC, @NullAdapterAddress,
SizeOf(NullAdapterAddress)) then
Addresses.Add(AdapterToString(MAC));
end;
end;
end;
end;
end;
end;
SnmpUtilVarBindFree(@VarBind[0]);
SnmpUtilVarBindFree(@VarBind[1]);
end;
finally
UnloadSnmpExtension;
end;
finally
UnloadSnmp;
end;
end;
begin
Result := -1;
Addresses.BeginUpdate;
try
Addresses.Clear;
GetMacAddressesNetBios;
if (Result <= 0) and (Machine = '') then
GetMacAddressesSnmp;
finally
Addresses.EndUpdate;
end;
end;
function GetMACaddress: string;
var
Addresses: TStringList;
begin
Addresses:= TStringList.Create;
if GetMacAddresses('', Addresses) >= 0 then
Result:= Addresses.Strings[0]
else
Result:= '';
end;
{$ENDIF MSWINDOWS}
end.
Andrea Mauri ha scritto:
> I still have to check it, I will try to use only the non visual units.
> I will post how I will solve it.
> andrea
>
> Andrea Mauri ha scritto:
>
>> thanks to all,
>> andrea
>>
>> Mattias Gaertner ha scritto:
>>
>>
>>> On Fri, 24 Apr 2009 19:22:35 +0200
>>> Vincent Snijders <[email protected]> wrote:
>>>
>>>
>>>
>>>
>>>> Andrea Mauri schreef:
>>>>
>>>>
>>>>
>>>>> Dear all,
>>>>> I have a cross-platform console application project.
>>>>> The project were compiled with no problem but actually when I
>>>>> compile it I get the following errors (WinXp lazarus svn fpc 2.2.4).
>>>>> I got this error both with fpc 2.2.2 and fpc 2.2.4, I don't know
>>>>> exactly when this error appears (the svn revision number of
>>>>> lazarus). Suggestions?
>>>>>
>>>>>
>>>>>
>>>> Remove the dependency on the LCL.
>>>>
>>>> Or if it must depend on the LCL, include uses interfaces to the main
>>>> program.
>>>>
>>>>
>>>>
>>> or use only the non visual units. For example lclproc, translations,
>>> etc.
>>>
>>> Mattias
>>> _______________________________________________
>>> Lazarus mailing list
>>> [email protected]
>>> http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
>>>
>>>
>>>
>>>
>>
>>
>
> _______________________________________________
> Lazarus mailing list
> [email protected]
> http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
>
>
_______________________________________________
Lazarus mailing list
[email protected]
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus