Link to home
Start Free TrialLog in
Avatar of koger
koger

asked on

Get computers on LAN

Hi

I have asked this question before, but I didn't really get the help I was looking for.
I want to get all computernames on the Local Network.
I have got a great program from:
http://www.delphifreestuff.com/examples/wnetexmp.zip
I run the app. on my Win98 network.
When I run the app. on aNT network it doesn't find anything.

Can anybody help me?
Avatar of Epsylon
Epsylon

oops, I should have read the question better.
haha, thats really funny epsylon :-) :-)

Cheers,

Raymond.
Maybe this is an alternative....

http://www.torry.ru/vcl/lan/netusers.zip
Hmmm... I guess not....
I can write one myself but that will take a day or 2.
Or I will try to get this one to work tomorrow.
Koger, can you be more precise about your problem? You say that on NT it shows nothing. Are there any direcories shared in the network?
Koger?
I guess you don't want it anymore.....
Please respond if you still need it.

By the way, what Delphi version do you have?
Avatar of koger

ASKER

Read the question again!!
That sample doesn't work
Avatar of koger

ASKER

Sorry Epsylon about the missing details.

I don't know that much about the network as I got a friend to test the program for me.

16mibit tokenring, on Windows NT with TCP/IP using DHCP

I have got a clue from someone that it might be the NetBeui protocol that caused problems, but I'm not sure.

I don't know if it's enough info.
That program only sees shared system and its shared directories. The same things you see in explorer under network neighbourhood.
Where there any drives shared when you tried that demo?

This demo may not be what you are looking for at all. I guess you want to rip data out of the DHCP server, right...

I'm afraid I can't help you with that but I will try some things....

Epsylon.
Avatar of koger

ASKER

The PC's are shared.
I can connect to the network with my win98 computer. I run the program and find all computers, then I copy the program to a PC using NT and I can't see one computer. That's the same network, only difference is th OS, the network properties seems to be equal.
Koger, I am working on a new object that should do the job. It is already working but I have to put the stuff into an object.....
Alright, it works!

Use the object like this:


uses Computers

procedure TForm1.Button1Click(Sender: TObject);
var c: TComputers;
begin
  TreeView1.Items.Clear;
  ListBox1.Clear;
  c := TComputers.Create(TreeView1); // pass nil if you don't need a TreeView
  ListBox1.Items.Assign(c.Computers);
  c.Free;
end;
And here is the object (Computers.pas):
-------------------------------------------------------------------
unit Computers;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ShlObj, ShellApi, ActiveX, ComCtrls;

type
  TComputers = class(TObject)
  private
    FShellMalloc: IMalloc;
    RootFolder: IShellFolder;
    Depth: Integer;
    NetWorkTree: TTreeView;
    function GetDisplayName(ShellFolder: IShellFolder;
                            PIDL: PItemIDList;
                            Flags: Cardinal): string;
    function GetSFFlags: DWORD;
    procedure Enumerate(parentfolder: IShellFolder;
                        pidl: PItemIDList;
                        node: TTreeNode);
    procedure FreePIDL(PIDL: PItemIDList);
  public
    Computers: TStringList;
    constructor Create(TreeView: TTreeView);
    destructor Destroy; override;
  end;

implementation

{ TComputers }

constructor TComputers.Create(TreeView: TTreeView);
var pidl: PItemIDList;
    tpidl: PItemIDList;
    folder: IShellFolder;
    EnumList: IEnumIDList;
    NumIDs: LongWord;
    Name: String;
    node: TTreeNode;
begin
  inherited Create;
  NetWorkTree := TreeView;
  Computers := TStringList.Create;
  SHGetMalloc(FShellMalloc);
  SHGetDesktopFolder(RootFolder);
  SHGetSpecialFolderLocation(Application.Handle, CSIDL_NETWORK, pidl);

  RootFolder.BindToObject(pidl, nil, IID_IShellFolder, Pointer(folder));
  if folder.EnumObjects(Application.Handle,GetSFFlags,EnumList) = NO_ERROR then
  begin
    if EnumList.Next(1, tpidl, NumIDs) = NO_ERROR then
    begin
      Name := GetDisplayName(folder, tpidl, SHGDN_INFOLDER);
      node := nil;
      if Assigned(NetWorkTree) then
        node := NetworkTree.Items.Add(nil, Name);
      Depth := 2;
      Enumerate(folder, tpidl, node);
      FreePIDL(tpidl);
    end;
  end;
  FreePIDL(pidl);
end;

destructor TComputers.Destroy;
begin
  Computers.Free;
  inherited;
end;

procedure TComputers.Enumerate(parentfolder: IShellFolder;
                           pidl: PItemIDList;
                           node: TTreeNode);
var tpidl: PItemIDList;
    folder: IShellFolder;
    EnumList: IEnumIDList;
    NumIDs: LongWord;
    Name: String;
    cnode: TTreeNode;
begin
  Dec(Depth);
  if Depth >= 0 then
  begin
    parentfolder.BindToObject(pidl, nil, IID_IShellFolder, Pointer(folder));
    if folder.EnumObjects(Application.Handle,GetSFFlags,EnumList) = NO_ERROR then
    begin
      while EnumList.Next(1, tpidl, NumIDs) = NO_ERROR do
      begin
        Name := GetDisplayName(folder, tpidl, SHGDN_INFOLDER);
        cnode := nil;
        if Assigned(NetWorkTree) then
          cnode := NetworkTree.Items.AddChild(node, Name);
        if Depth = 0 then
          Computers.Add(Name);
        Enumerate(folder, tpidl, cnode);
        FreePIDL(tpidl);
      end;
    end;
  end;
  Inc(Depth);
end;

function TComputers.GetSFFlags: DWORD;
begin
  Result:= SHCONTF_FOLDERS{ or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN};
end;

function TComputers.GetDisplayName(ShellFolder: IShellFolder;
                               PIDL: PItemIDList;
                               Flags: Cardinal): string;
var StrRet: TStrRet;
    P: PChar;
begin
  Result := '';
  ShellFolder.GetDisplayNameOf(PIDL, Flags, StrRet);
  case StrRet.uType of
    STRRET_CSTR:
      SetString(Result, StrRet.cStr, lStrLen(StrRet.cStr));
    STRRET_OFFSET:
      begin
        P := @PIDL.mkid.abID[StrRet.uOffset - SizeOf(PIDL.mkid.cb)];
        SetString(Result, P, PIDL.mkid.cb - StrRet.uOffset);
      end;
    STRRET_WSTR:
      Result := StrRet.pOleStr;
  end;
end;

procedure TComputers.FreePIDL(PIDL: PItemIDList);
begin
  if Assigned(PIDL) then FShellMalloc.Free(PIDL);
end;

end.
Did you get it to work?
Hello?
>LOCK<
Avatar of koger

ASKER

Adjusted points to 267
Avatar of koger

ASKER

Adjusted points to 317
Avatar of koger

ASKER

Hi Epsylon

My friend has been on hollyday so I couldn't test it on his network, therefore the delay.

I almost works, on my Win98 computer it works 100%, but on the NT with multiple domain/workgroups it doesn't find the users but only the workgroups, perhaps because the code should loop another time. I have a screenshot that my help you, I can email you the picture. You may email me at koger@iname.com
Mail to Epsylon3@hotmail.com
Now I see what you mean.

In Computers.pas change

Depth := 2;

to

Depth := 3;


Now it searches one level deeper.

Eps.

Avatar of koger

ASKER

I have tried it out today, this seems to work, but what if the program is runned on a system that should only use depth:=2. I have looked at IShellFolder::GetAttributesOf, because I thought I could get to know if the folder was a domain/group or .., is there another way to get the folderattribute?
I have a little problem because I don't have an NT system right now to test it (vacation :o).

Does the depth difference only occur between NT and 95/98 or also between different NT systems?
Avatar of koger

ASKER

I have only tested it on one NT System, I must allow I don't know that much about network setup, so I don't know if this i common. In this case the NT Network "inserts" "Microsoft Windows Networks" before the domain/groups is displayed. The depth const may be changed depending if the OS is NT/98 or if "Microsoft Windows Networks"-text is found.
But what if other networks are connect how do you know the difference then
It's no big deal to check the OS and set Depth to 3 for NT and to 2 for 95/98. And even checking for "Microsoft Windows Networks" is not impossible unless another language is used.

>But what if other networks are connect how do you know the difference then

I think you can't tell. These other networks just appear in the list/tree too.

I wonder if that works on NT.....
Avatar of koger

ASKER

No but I have tried it before, without luck :-(
I tried

http://www.delphipages.com/edit/count.cfm?comID=414&Link=uploads%2FMiscellaneous%2FNetUsers%2Ezip 

on 4 different NT systems in 2 different LAN's today. In each LAN I tried a Workstation and a Server. NetUsers worked on all of them!!!

What could be wrong...?

I don't know what else I can do but posting a new version of my component that check the platform it runs on...
unit Computers;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ShlObj, ShellApi, ActiveX, ComCtrls;

type
  TComputers = class(TObject)
  private
    FShellMalloc: IMalloc;
    RootFolder: IShellFolder;
    Depth: Integer;
    NetWorkTree: TTreeView;
    function GetDisplayName(ShellFolder: IShellFolder;
                            PIDL: PItemIDList;
                            Flags: Cardinal): string;
    function GetSFFlags: DWORD;
    procedure Enumerate(parentfolder: IShellFolder;
                        pidl: PItemIDList;
                        node: TTreeNode);
    procedure FreePIDL(PIDL: PItemIDList);
    function OSVersion: DWord;
  public
    Computers: TStringList;
    constructor Create(TreeView: TTreeView);
    destructor Destroy; override;
  end;

implementation

{ TComputers }

constructor TComputers.Create(TreeView: TTreeView);
var pidl: PItemIDList;
    tpidl: PItemIDList;
    folder: IShellFolder;
    EnumList: IEnumIDList;
    NumIDs: LongWord;
    Name: String;
    node: TTreeNode;
begin
  inherited Create;
  NetWorkTree := TreeView;
  Computers := TStringList.Create;
  SHGetMalloc(FShellMalloc);
  SHGetDesktopFolder(RootFolder);
  SHGetSpecialFolderLocation(Application.Handle, CSIDL_NETWORK, pidl);

  RootFolder.BindToObject(pidl, nil, IID_IShellFolder, Pointer(folder));
  if folder.EnumObjects(Application.Handle,GetSFFlags,EnumList) = NO_ERROR then
  begin
    if EnumList.Next(1, tpidl, NumIDs) = NO_ERROR then
    begin
      Name := GetDisplayName(folder, tpidl, SHGDN_INFOLDER);
      node := nil;
      if Assigned(NetWorkTree) then
        node := NetworkTree.Items.Add(nil, Name);
      if OSVersion = VER_PLATFORM_WIN32_NT then
        Depth := 3
      else
        Depth := 2;
      Enumerate(folder, tpidl, node);
      FreePIDL(tpidl);
    end;
  end;
  FreePIDL(pidl);
end;

destructor TComputers.Destroy;
begin
  Computers.Free;
  inherited;
end;

procedure TComputers.Enumerate(parentfolder: IShellFolder;
                           pidl: PItemIDList;
                           node: TTreeNode);
var tpidl: PItemIDList;
    folder: IShellFolder;
    EnumList: IEnumIDList;
    NumIDs: LongWord;
    Name: String;
    cnode: TTreeNode;
begin
  Dec(Depth);
  if Depth >= 0 then
  begin
    parentfolder.BindToObject(pidl, nil, IID_IShellFolder, Pointer(folder));
    if folder.EnumObjects(Application.Handle,GetSFFlags,EnumList) = NO_ERROR then
    begin
      while EnumList.Next(1, tpidl, NumIDs) = NO_ERROR do
      begin
        Name := GetDisplayName(folder, tpidl, SHGDN_INFOLDER);
        cnode := nil;
        if Assigned(NetWorkTree) then
          cnode := NetworkTree.Items.AddChild(node, Name);
        if Depth = 0 then
          Computers.Add(Name);
        Enumerate(folder, tpidl, cnode);
        FreePIDL(tpidl);
      end;
    end;
  end;
  Inc(Depth);
end;

function TComputers.GetSFFlags: DWORD;
begin
  Result:= SHCONTF_FOLDERS{ or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN};
end;

function TComputers.GetDisplayName(ShellFolder: IShellFolder;
                               PIDL: PItemIDList;
                               Flags: Cardinal): string;
var StrRet: TStrRet;
    P: PChar;
begin
  Result := '';
  ShellFolder.GetDisplayNameOf(PIDL, Flags, StrRet);
  case StrRet.uType of
    STRRET_CSTR:
      SetString(Result, StrRet.cStr, lStrLen(StrRet.cStr));
    STRRET_OFFSET:
      begin
        P := @PIDL.mkid.abID[StrRet.uOffset - SizeOf(PIDL.mkid.cb)];
        SetString(Result, P, PIDL.mkid.cb - StrRet.uOffset);
      end;
    STRRET_WSTR:
      Result := StrRet.pOleStr;
  end;
end;

procedure TComputers.FreePIDL(PIDL: PItemIDList);
begin
  if Assigned(PIDL) then FShellMalloc.Free(PIDL);
end;

function TComputers.OSVersion: DWord;
var v: TOSVersionInfo;
begin
  v.dwOSVersionInfoSize := sizeof(v);
  if GetVersionEx(v) then
    Result := v.dwPlatformId
  else
    Result := 0;
end;

end.
Avatar of koger

ASKER

Hold your horsepowers I think I have made a big mistake. I have downloaded the netusers component some days ago, but it seems to be another version that the one you gave. I havn't tried it on NT yet, but if you say it works on a NT computer where the app. from http://www.delphifreestuff.com/examples/wnetexmp.zip didn't work, i'll guess that it works. I will let you on Monday/Tuesday
Still no luck?
oh god. koger, i think epsylon deserved that all 317 points.. :)
Avatar of koger

ASKER

It works, my friend took a little long to test it. Go make  answer ;-)
ASKER CERTIFIED SOLUTION
Avatar of Epsylon
Epsylon

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
so everybody is happy. how nice.
:)