Recent

Author Topic: Reading MAC address of ethernet (wifi) from WinCE device  (Read 11589 times)

ertank

  • Full Member
  • ***
  • Posts: 244
Reading MAC address of ethernet (wifi) from WinCE device
« on: March 10, 2016, 04:37:06 pm »
Hi,

I have found several threads in forum.lazarus about subject. Unfortunately, none of them worked for me.

Is there any one which already could get this piece of information?

Thanks.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #1 on: March 11, 2016, 02:59:29 am »
hello,
you can try using tprocess and  tregexpr  with the command ipconfig /all.

something like that ( description and mac address of each network adapter)  :

Code: Pascal  [Select]
  1. // uses process,regexpr;
  2. procedure TForm1.ReadAdapterInfos();
  3.       const READ_BYTES = 2048;
  4.       var
  5.       i : integer;
  6.       Re1,Re2: TRegExpr;
  7.       aProcess: TProcess; //TProcess is crossplatform is best way
  8.       MemStream: TMemoryStream;
  9.       NumBytes: LongInt;
  10.       BytesRead: LongInt;
  11.       Lines: TStringList;
  12.     begin
  13.      // A temp Memorystream is used to buffer the output
  14.      MemStream := TMemoryStream.Create;
  15.      Lines :=TStringList.Create;
  16.      BytesRead := 0;
  17.       try
  18.        re1 := TRegExpr.Create;
  19.        // regex for description of network adapter
  20.        re1.Expression := '.*Description.*:(.+)';
  21.        re2 :=  TRegExpr.Create;
  22.        // regex for mac address
  23.        re2.Expression := '.*Adresse physique.*:(.+)';
  24.        aProcess := TProcess.Create(nil);
  25.        aProcess.Executable := 'ipconfig.exe';
  26.        aProcess.Parameters.Add('/all');
  27.        aprocess.ShowWindow := swoHIDE;
  28.        AProcess.Options := AProcess.Options + [poUsePipes,poStderrToOutPut];
  29.        Memo1.Lines.Clear;
  30.        aProcess.Execute;
  31.        while aProcess.Running do
  32.        begin
  33.          // make sure we have room
  34.          MemStream.SetSize(BytesRead + READ_BYTES);
  35.          // try reading it
  36.          NumBytes := aProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
  37.          if NumBytes > 0 // All read() calls will block, except the final one.
  38.             then Inc(BytesRead, NumBytes)
  39.          else
  40.             BREAK // Program has finished execution.
  41.        end;
  42.        MemStream.SetSize(BytesRead);
  43.        Lines.LoadFromStream(MemStream);
  44.        for i := 0 to Lines.Count-1 do
  45.        begin
  46.        if re1.Exec(Lines[i]) then  Memo1.lines.Add(Trim(Re1.Match[1]));
  47.        if re2.Exec(Lines[i]) then  Memo1.lines.Add(Trim(Re2.Match[1]));
  48.        end;
  49.        finally
  50.        re1.Free;
  51.        re2.Free;
  52.        aProcess.Free;
  53.        Lines.Free;
  54.        MemStream.Free;
  55.        end;
  56.     end;        

1 - The expressions for the regexp are trivial -> can be optimized
2 - The expression of re2 for mac address must be changed depending of the country. In the example it is for french Ipconfig.

Friendly J.P
« Last Edit: March 11, 2016, 03:09:58 am by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #2 on: April 08, 2016, 04:29:45 pm »
Hi,

Thanks for the sample code. I tried to use it. However, my WinCE device insists not to run ipconfig.exe

First, I get "Cannot execute empty command-line" error message. Then I also assign "ipconfig.exe" to aProcess.CommandLine (which supposed to be depreciated).
Second, I started to get "Failed to execute ipconfig.exe : 87" which I have no idea what it means.

I tested and confirm that my device has ipconfig.exe and it executes as expected from command shell.

Are you able to support on above problems?

Thanks.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #3 on: April 08, 2016, 05:44:19 pm »
 hello,
try to call the command-line interpreter before the command : 
Code: Pascal  [Select]
  1.  AProcess.Executable := 'cmd.exe'; // or with the whole path
  2.     AProcess.Parameters.Add('/c');
  3.     AProcess.Parameters.Add('ipconfig.exe');
  4.     AProcess.Parameters.Add('/all');
  5.  

Friendly, J.P
« Last Edit: April 08, 2016, 05:52:14 pm by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #4 on: April 08, 2016, 11:18:55 pm »
Hi,

I didn't mention earlier. I am using Lazaus 1.6.0. Cross compiler for ARM is installed.

Still receiving error saying "Cannot execute empty command-line" again. I suppose I need to put something in aProcess.CommandLine parameter. This parameter is depreciated as it is indicated though. Current code is as follows:
I have some type casting to prevent compiler warnings.

Code: Pascal  [Select]
  1. // uses process,regexpr;
  2. function TDM.ReadAdapterInfos:String;
  3. const READ_BYTES = 2048;
  4. var
  5. i : integer;
  6. Re1,Re2: TRegExpr;
  7. aProcess: TProcess; //TProcess is crossplatform is best way
  8. MemStream: TMemoryStream;
  9. NumBytes: LongInt;
  10. BytesRead: LongInt;
  11. Lines: TStringList;
  12. begin
  13.   Result := EmptyStr;
  14.   // A temp Memorystream is used to buffer the output
  15.   MemStream := TMemoryStream.Create;
  16.   Lines :=TStringList.Create;
  17.   BytesRead := 0;
  18.   try
  19.     re1 := TRegExpr.Create;
  20.     // regex for description of network adapter
  21.     re1.Expression := '.*Description.*:(.+)';
  22.     re2 :=  TRegExpr.Create;
  23.     // regex for mac address
  24.     re2.Expression := '.*Adresse physique.*:(.+)';
  25.     aProcess := TProcess.Create(nil);
  26.     AProcess.Executable := 'cmd.exe'; // or with the whole path
  27.     AProcess.Parameters.Add('/c');
  28.     AProcess.Parameters.Add('ipconfig.exe');
  29.     AProcess.Parameters.Add('/all');
  30.     AProcess.ShowWindow := swoHIDE;
  31.     AProcess.Options := AProcess.Options + [poUsePipes,poStderrToOutPut];
  32.     aProcess.Execute;
  33.     while aProcess.Running do begin
  34.       // make sure we have room
  35.       MemStream.SetSize(BytesRead + READ_BYTES);
  36.       // try reading it
  37.       NumBytes := aProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
  38.       if NumBytes > 0 // All read() calls will block, except the final one.
  39.         then Inc(BytesRead, NumBytes)
  40.       else
  41.         BREAK // Program has finished execution.
  42.     end;
  43.     MemStream.SetSize(BytesRead);
  44.     Lines.LoadFromStream(MemStream);
  45.     for i := 0 to Lines.Count-1 do begin
  46.       if re1.Exec(WideString(Lines[i])) then  Result := Result + #13 + Trim(string(Re1.Match[1]));
  47.       if re2.Exec(WideString(Lines[i])) then  Result := Result + #13 + Trim(string(Re2.Match[1]));
  48.     end;
  49.   finally
  50.     re1.Free;
  51.     re2.Free;
  52.     aProcess.Free;
  53.     Lines.Free;
  54.     MemStream.Free;
  55.   end;
  56. end;
  57.  

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #5 on: April 09, 2016, 12:22:58 am »
hello,
it seems that  executable + parameters are not used for wince version of Tprocess    :o

windows
1 - lazarus_1_6_0\fpc\3.0.0\source\packages\fcl-process\src\win\process.inc
Code: Pascal  [Select]
  1.  if (FApplicationName<>'') then
  2.     begin
  3.     PName:=Pchar(FApplicationName);
  4.     PCommandLine:=Pchar(FCommandLine);
  5.     end
  6.   else If (FCommandLine<>'') then
  7.     PCommandLine:=Pchar(FCommandLine)
  8.   else if (Fexecutable<>'') then
  9.     begin
  10.     Cmd:=MaybeQuoteIfNotQuoted(Executable);
  11.     For I:=0 to Parameters.Count-1 do
  12.       Cmd:=Cmd+' '+MaybeQuoteIfNotQuoted(Parameters[i]);
  13.  
  14.     PCommandLine:=PChar(Cmd);

Wince
2 - F:\lazarus_1_6_0\fpc\3.0.0\source\packages\fcl-process\src\wince\process.inc
Code: Pascal  [Select]
  1.  if (FApplicationName='') then
  2.     begin
  3.       If (FCommandLine='') then
  4.         Raise EProcess.Create(SNoCommandline);
  5.       PCommandLine:=PWidechar(FCommandLine)
  6.     end
  7.   else
  8.     begin
  9.       PName:=PWidechar(FApplicationName);
  10.       If (FCommandLine='') then
  11.         PCommandLine:=PWidechar(FApplicationName)
  12.       else
  13.         PCommandLine:=PWidechar(FCommandLine)
  14.     end;

then try this :
Code: Pascal  [Select]
  1. AProcess.CommandLine := 'cmd.exe  /c Ipconfig.exe /all';

Friendly, J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #6 on: April 09, 2016, 12:44:50 am »
Now we are back to that mysterious "error 87" My debug log contains below lines:

Code: Pascal  [Select]
  1. TApplication.HandleException Failed to execute cmd.exe  /c Ipconfig.exe /all : 87
  2. TApplication.HandleException Failed to execute ipconfig.exe /all : 87
  3. TApplication.HandleException Failed to execute \windows\ipconfig.exe /all : 87
  4.  

I, myself, out of ideas here.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #7 on: April 09, 2016, 01:06:07 am »
error code 87 for wince :

Quote
87    The parameter is incorrect.
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #8 on: April 09, 2016, 01:09:23 am »
Sure, meaning of error 87 is known. Reason is not. Everything seems in order for our command line. I have found below link related with my problem. They were not able to use TProcess in the end, too.

http://forum.lazarus.freepascal.org/index.php?topic=3683.0

So, I'm stuck.

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #9 on: April 09, 2016, 12:56:53 pm »
Finally, I could read ethernet MAC address (not bluetooth though).

My source link: http://forum.lazarus.freepascal.org/index.php?topic=10465.0

I needed to modify some parts of the code to be able to compile it for WinCE. Below is my complete unit code:

Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus,
  9.   StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button2: TButton;
  17.     Memo1: TMemo;
  18.     procedure Button1Click(Sender: TObject);
  19.     procedure Button2Click(Sender: TObject);
  20.     procedure FormCreate(Sender: TObject);
  21.   private
  22.     { private declarations }
  23.     function GetWinMacAddress: String;
  24.   public
  25.     { public declarations }
  26.   end;
  27.  
  28.   function GetIfTable( pIfTable : Pointer;
  29.                    VAR pdwSize  : LongInt;
  30.                        bOrder   : LongInt ): LongInt; stdcall;
  31. var
  32.   Form1: TForm1;
  33.  
  34. implementation
  35.  
  36. {$R *.lfm}
  37.  
  38. function GetIfTable( pIfTable : Pointer;
  39.                  VAR pdwSize  : LongInt;
  40.                      bOrder   : LongInt ): LongInt; stdcall; external 'IPHLPAPI.DLL';
  41.  
  42. { TForm1 }
  43.  
  44. procedure TForm1.FormCreate(Sender: TObject);
  45. begin
  46.   // Below is necessary to be able to see form on the mini device screen
  47.   Left := 0;
  48.   Top  := 25;
  49. end;
  50.  
  51. procedure TForm1.Button2Click(Sender: TObject);
  52. begin
  53.   Memo1.Lines.Add(EmptyStr);
  54.   Memo1.Lines.Add(GetWinMacAddress);
  55. end;
  56.  
  57. function TForm1.GetWinMacAddress: String;
  58. const
  59.   MAX_INTERFACE_NAME_LEN             = $100;
  60.   ERROR_SUCCESS                      = 0;
  61.   MAXLEN_IFDESCR                     = $100;
  62.   MAXLEN_PHYSADDR                    = 8;
  63.  
  64.   MIB_IF_TYPE_ETHERNET               = 6;
  65.  
  66.   _MAX_ROWS_ = 20;
  67.  
  68. type
  69.  
  70.    MIB_IFROW            = Record
  71.      wszName : Array[0 .. (MAX_INTERFACE_NAME_LEN * 2 - 1)] of char;
  72.      dwIndex              : LongInt;
  73.      dwType               : LongInt;
  74.      dwMtu                : LongInt;
  75.      dwSpeed              : LongInt;
  76.      dwPhysAddrLen        : LongInt;
  77.      bPhysAddr : Array[0 .. (MAXLEN_PHYSADDR-1)] of Byte;
  78.      dwAdminStatus        : LongInt;
  79.      dwOperStatus         : LongInt;
  80.      dwLastChange         : LongInt;
  81.      dwInOctets           : LongInt;
  82.      dwInUcastPkts        : LongInt;
  83.      dwInNUcastPkts       : LongInt;
  84.      dwInDiscards         : LongInt;
  85.      dwInErrors           : LongInt;
  86.      dwInUnknownProtos    : LongInt;
  87.      dwOutOctets          : LongInt;
  88.      dwOutUcastPkts       : LongInt;
  89.      dwOutNUcastPkts      : LongInt;
  90.      dwOutDiscards        : LongInt;
  91.      dwOutErrors          : LongInt;
  92.      dwOutQLen            : LongInt;
  93.      dwDescrLen           : LongInt;
  94.      bDescr     : Array[0 .. (MAXLEN_IFDESCR - 1)] of Char;
  95.      end;
  96.  
  97.    _IfTable = Record
  98.                  nRows : LongInt;
  99.                  ifRow : Array[1.._MAX_ROWS_] of MIB_IFROW;
  100.               end;
  101.  
  102. var
  103.    pIfTable  : ^_IfTable;
  104.    TableSize : LongInt;
  105.    tmp       : String;
  106.    i,j       : Integer;
  107.    ErrCode   : LongInt;
  108. begin
  109.    pIfTable := nil;
  110.    //------------------------------------------------------------
  111.    Result := '';
  112.    try
  113.       //-------------------------------------------------------
  114.       // First: just get the buffer size.
  115.       // TableSize returns the size needed.
  116.       TableSize := 0; // Set to zero so the GetIfTabel function
  117.                     // won't try to fill the buffer yet,
  118.                     // but only return the actual size it needs.
  119.       GetIfTable(pIfTable, TableSize, 1);
  120.       if (TableSize < SizeOf(MIB_IFROW) + Sizeof(LongInt)) then
  121.       begin
  122.          Exit; // less than 1 table entry?!
  123.       end; // if-end.
  124.  
  125.       // Second:
  126.       // allocate memory for the buffer and retrieve the
  127.       // entire table.
  128.       GetMem(pIfTable, TableSize);
  129.       ErrCode := GetIfTable(pIfTable, TableSize, 1);
  130.       if (ErrCode <> ERROR_SUCCESS) then
  131.       begin
  132.          Exit; // OK, that did not work.
  133.                // Not enough memory i guess.
  134.       end; // if-end.
  135.  
  136.       // Read the ETHERNET addresses.
  137.       for i := 1 to pIfTable^.nRows do
  138.       try
  139.          if (pIfTable^.ifRow[i].dwType=MIB_IF_TYPE_ETHERNET) and
  140.              (pIfTable^.ifRow[i].dwOutOctets <> 0) then
  141.          begin
  142.             tmp := '';
  143.             for j:=0 to pIfTable^.ifRow[i].dwPhysAddrLen-1 do
  144.             begin
  145.                tmp := tmp + format('%.2x:',
  146.                       [ pIfTable^.ifRow[i].bPhysAddr[j] ] );
  147.             end; // for-end.
  148.             //-------------------------------------
  149.             if Length(tmp)>0 then
  150.             begin
  151.               Result := Copy(tmp, 1, Length(tmp) - 1);
  152.               Exit;
  153.             end;
  154.          end; // if-end.
  155.       except
  156.          Exit;
  157.       end; // if-try-except-end.
  158.    finally
  159.       if Assigned(pIfTable) then FreeMem(pIfTable, TableSize);
  160.    end; // if-try-finally-end.
  161. end;
  162.  
  163. end.
  164.  

Solution is not what we were trying to achieve, but it's same result, different path.

Thanks for all the support.

Regards,
Ertan Küçükoğlu


Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #10 on: April 09, 2016, 01:37:58 pm »
hello,
you can try also to use the iphlpapi   unit like that :


Code: Pascal  [Select]
  1. // uses iphlpapi
  2.  
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. var pAdapterInfo:PIP_ADAPTER_INFO;
  5.    BufLen,Status:cardinal; i:Integer;
  6.    tmp : string;
  7. begin
  8.   BufLen:= sizeof(IP_ADAPTER_INFO);
  9.   GetAdaptersInfo(nil, BufLen);
  10.   pAdapterInfo:= AllocMem(BufLen);
  11.   try
  12.     Status:= GetAdaptersInfo(pAdapterInfo,BufLen);
  13.     if (Status = 0 ) then
  14.     begin
  15.       while (pAdapterInfo<>nil) do
  16.     begin
  17.     tmp := '';
  18.     if pAdapterInfo^.AddressLength>0 then
  19.     for i := 0 to pAdapterInfo^.AddressLength - 1 do
  20.       tmp :=  tmp + IntToHex(pAdapterInfo^.Address[I], 2) + ' ';
  21.      memo1.Append(tmp);
  22.      pAdapterInfo:=pAdapterInfo^.next;
  23.     end;
  24.     end;
  25.   finally
  26.     Freemem(pAdapterInfo);
  27.   end;
  28. end;      

it's OK for me on my old PDA   Fuji Loox 420    PXA255   with      wince (pocket pc)  4.2   
need to activate WLAN to see the MAC address of the Wifi adapter.

Friendly, J.P 
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #11 on: April 09, 2016, 02:24:55 pm »
That seems to be another solution. Shorter, easier to read.

Are you sure that you need to activate WiFi in order to read MAC address? I tested my code when WiFi is closed and it run OK.

Thanks.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #12 on: April 09, 2016, 02:30:53 pm »
on my device (fuji Loox 420) when i disable WLAN, i can't see the Wifi adapter infos from my program. What is your device ?
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

ertank

  • Full Member
  • ***
  • Posts: 244
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #13 on: April 09, 2016, 02:36:44 pm »
Producer is Korean. Web address: http://www.dsic.co.kr/ You can find it under Mobile Solutions. Model is DS5

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 753
Re: Reading MAC address of ethernet (wifi) from WinCE device
« Reply #14 on: April 09, 2016, 02:43:35 pm »
your PDA is  relatively recent , mine is jurassic ( 2004)   ;D
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko