Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Scan the local network

Status
Not open for further replies.

akshin777

Programmer
Aug 3, 2021
5
AZ
Hi.
Please help me what's wrong.
Below is the code that scans the local network.
Everything in {} is my experiments (unsuccessful)

Result
i: 0
i: 0 i2: 0
i: 0 i2: 1 Microsoft Terminal Services
i: 0 i2: 2 Microsoft Windows Network
i: 1 Microsoft Terminal Services
i: 2 Microsoft Windows Network

Code:
procedure TForm1.Button16Click(Sender: TObject);
Type
  PNRArr = ^TNRArr;
  TNRArr = array[0..512] of TNetResourceW;
var Result1,Result2,Result3,Result4,EntrReq,EntrReq2,SizeReq,SizeReq2: Cardinal;
    twx,twx2: NativeUInt;
    x,x2: array[1..MaxEntries] of TNetResource;{PNRArr;}{PNETRESOURCE;}
    i,i2:integer;
    //Network,Network2: TNetResource;
begin



{ FillChar(Network, SizeOf(Network), 0);
 with Network do
 begin
  dwScope := RESOURCE_GLOBALNET;
  dwType := RESOURCETYPE_ANY;
  dwUsage := RESOURCEUSAGE_CONTAINER;
 end;}



 Result1 :=WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, RESOURCEUSAGE_CONTAINER, nil{@Network}, twx);
 case Result1 of
  0: begin
       //showmessage('WNetOpenEnum NO_ERROR '+twx.ToString);
       if twx<>0 then
       begin
        //New(x);
        SizeReq := {16384}SizeOf(x);
        EntrReq := Cardinal(-1);
        //x  := PNETRESOURCE(GlobalAlloc(GPTR, SizeReq));
        Result2 := WNetEnumResource(twx, EntrReq, @x, SizeReq);
        case Result2 of
          NO_ERROR:
           begin
            //showmessage('WNetEnumResource NO_ERROR '+EntrReq.ToString);
            For i := 0 To EntrReq - 1 do
            begin
             RichEdit1.Lines.Add('i: '+i.ToString+' '+x[i].lpRemoteName);


             Result3 := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, {RESOURCEUSAGE_CONTAINER}0, @x[i], twx2);
             case Result3 of
               NO_ERROR:
                begin
                 //showmessage('i: '+i.ToString+' WNetOpenEnum2 NO_ERROR '+twx2.ToString);

                 SizeReq2 := SizeOf(x2);
                 EntrReq2 := Cardinal(-1);
                 Result4 := WNetEnumResource(twx2, EntrReq2, @x2, SizeReq2);
                 case Result4 of
                  NO_ERROR:
                   begin


                    //showmessage('i: '+i.ToString+' WNetEnumResource2 NO_ERROR '+EntrReq2.ToString);
                    For i2 := 0 To EntrReq2 - 1 do
                     begin
                      RichEdit1.Lines.Add('i: '+i.ToString+' i2: '+i2.ToString+' '+x2[i2].lpRemoteName);
                     end;



                   end;
                  {ERROR_NO_NETWORK: showmessage('i: '+i.ToString+' WNetEnumResource2 ERROR_NO_NETWORK '+EntrReq2.ToString);}
                  else showmessage('i: '+i.ToString+' Result4: '+Result4.ToString+' WNetEnumResource2 '+EntrReq2.ToString);
                 end;
                 WNetCloseEnum(twx2);
                end;
               {1222: showmessage('i: '+i.ToString+' WNetOpenEnum2 ERROR_NO_NETWORK '+twx2.ToString);
               else showmessage('i: '+i.ToString+' Result3: '+Result3.ToString+' WNetOpenEnum2 '+EntrReq2.ToString);}
             end;
            end;
            WNetCloseEnum(twx);
           end;
          {ERROR_NO_NETWORK: showmessage('WNetEnumResource ERROR_NO_NETWORK '+EntrReq.ToString);
          else showmessage('Result2: '+Result2.ToString+' WNetEnumResource '+EntrReq.ToString);}
        end;
       end;

     end;
  {1222: showmessage('WNetOpenEnum ERROR_NO_NETWORK '+twx.ToString);
  else showmessage('Result1: '+Result1.ToString+' WNetOpenEnum '+EntrReq.ToString);}
 end;
 //WNetCloseEnum(twx);
end;
 
Result
i: 0
i: 0 i2: 0
i: 0 i2: 1 Microsoft Terminal Services
i: 0 i2: 2 Microsoft Windows Network
i: 1 Microsoft Terminal Services
i: 2 Microsoft Windows Network

But I want to get a list of computers on the local network
 
By a long pause, I understand that scan the network on Delphi is not possible.
Or is it a top secret))
 
It is very possible. I wrote a scanner about 12 years ago for the company I worked for. Unfortunately, I don't have the code. I just haven't had the time to get back to this. It looks like you're not going far enough into the WNetEnumResource list. I found a console app (at that seems to work for me. That code is:

Code:
{$APPTYPE CONSOLE}

uses
  StrUtils,
  Windows,
  WinSock,
  SysUtils;

type
  PNetResourceArray = ^TNetResourceArray;
  TNetResourceArray = array[0..1023] of TNetResource;

function SendArp(DestIP,SrcIP:ULONG;pMacAddr:pointer;PhyAddrLen:pointer) : DWord; StdCall; external 'iphlpapi.dll' name 'SendARP';

function GetIPAddress(const HostName: AnsiString): AnsiString;
var
  HostEnt: PHostEnt;
  Host: AnsiString;
  SockAddr: TSockAddrIn;
begin
  Result := '';
  Host := HostName;
  if Host = '' then
  begin
    SetLength(Host, MAX_PATH);
    GetHostName(PAnsiChar(Host), MAX_PATH);
  end;
  HostEnt := GetHostByName(PAnsiChar(Host));
  if HostEnt <> nil then
  begin
    SockAddr.sin_addr.S_addr := Longint(PLongint(HostEnt^.h_addr_list^)^);
    Result := inet_ntoa(SockAddr.sin_addr);
  end;
end;


function GetMacAddr(const IPAddress: AnsiString; var ErrCode : DWORD): AnsiString;
var
 MacAddr    : Array[0..5] of Byte;
 DestIP     : ULONG;
 PhyAddrLen : ULONG;
begin
  Result    :='';
  ZeroMemory(@MacAddr,SizeOf(MacAddr));
  DestIP    :=inet_addr(PAnsiChar(IPAddress));
  PhyAddrLen:=SizeOf(MacAddr);
  ErrCode   :=SendArp(DestIP,0,@MacAddr,@PhyAddrLen);
  if ErrCode = S_OK then
   Result:=AnsiString(Format('%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x',[MacAddr[0], MacAddr[1],MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5]]));
end;


function ParseRemoteName(Const lpRemoteName : string) : string;
begin
  Result:=lpRemoteName;
  if StartsStr('\\', lpRemoteName) and (Length(lpRemoteName)>2) and (LastDelimiter('\', lpRemoteName)>2) then
   Result:=Copy(lpRemoteName, 3, PosEx('\', lpRemoteName,3)-3)
  else
  if StartsStr('\\', lpRemoteName) and (Length(lpRemoteName)>2) and (LastDelimiter('\', lpRemoteName)=2) then
   Result:=Copy(lpRemoteName, 3, length(lpRemoteName));
end;


function CreateNetResourceList(ResourceType: DWord;
                              NetResource: PNetResource;
                              out Entries: DWord;
                              out List: PNetResourceArray): Boolean;
var
  EnumHandle: THandle;
  BufSize: DWord;
  Res: DWord;
begin
  Result := False;
  List := Nil;
  Entries := 0;
  if WNetOpenEnum(RESOURCE_GLOBALNET, ResourceType, 0, NetResource, EnumHandle) = NO_ERROR then
  begin
    try
      BufSize := $4000;  // 16 kByte
      GetMem(List, BufSize);
      try
        repeat
          Entries := DWord(-1);
          FillChar(List^, BufSize, 0);
          Res := WNetEnumResource(EnumHandle, Entries, List, BufSize);
          if Res = ERROR_MORE_DATA then
          begin
            ReAllocMem(List, BufSize);
          end;
        until Res <> ERROR_MORE_DATA;

        Result := Res = NO_ERROR;
        if not Result then
        begin
          FreeMem(List);
          List := Nil;
          Entries := 0;
        end;
      except
        FreeMem(List);
        raise;
      end;
    finally
      WNetCloseEnum(EnumHandle);
    end;
  end;
end;

procedure ScanNetworkResources(ResourceType, DisplayType: DWord);

procedure ScanLevel(NetResource: PNetResource);
var
  Entries: DWord;
  NetResourceList: PNetResourceArray;
  i: Integer;
  IPAddress, MacAddress : AnsiString;
  ErrCode : DWORD;
begin
  if CreateNetResourceList(ResourceType, NetResource, Entries, NetResourceList) then try
    for i := 0 to Integer(Entries) - 1 do
    begin
      if (DisplayType = RESOURCEDISPLAYTYPE_GENERIC) or
        (NetResourceList[i].dwDisplayType = DisplayType) then
        begin
          IPAddress   :=GetIPAddress(ParseRemoteName(AnsiString(NetResourceList[i].lpRemoteName)));
          MacAddress  :=GetMacAddr(IPAddress, ErrCode);
          Writeln(Format('Remote Name %s Ip %s MAC %s',[NetResourceList[i].lpRemoteName, IPAddress, MacAddress]));
        end;
      if (NetResourceList[i].dwUsage and RESOURCEUSAGE_CONTAINER) <> 0 then
        ScanLevel(@NetResourceList[i]);
    end;
  finally
    FreeMem(NetResourceList);
  end;
end;

begin
  ScanLevel(Nil);
end;

var
  WSAData: TWSAData;
begin
  try
   if WSAStartup($0101, WSAData)=0 then
   try
     ScanNetworkResources(RESOURCETYPE_ANY, RESOURCEDISPLAYTYPE_GENERIC);
     Writeln('Done');
   finally
     WSACleanup;
   end;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
  Readln;
end.

Mirtheil
 
Im sorry.
There is result of the program
Only mac address no IP address

Remote Name Microsoft Terminal Services Ip MAC 56-11-45-E9-34-BC
Remote Name Microsoft Windows Network Ip MAC 56-11-45-E9-34-BC
Remote Name Web Client Network Ip MAC 56-11-45-E9-34-BC
Done

Scan_wkn1cy.png
 
There are scanners such as wireless network watcher and advanced ip scanner. How do these programs scan the network? What api functions are used?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top