pjelias
asked on
Obtaining PC Names for PC's on a Windows 2000 Server
Hi,
We have a Network running a Hundred or so Servers (All running Win2000) over a single domain, ie. DOMAIN, with each Server having a name ie. N123, N124 etc...
There are a list of Servers that our area looks after (About 20).
We are wanting to conduct an audit on PC's that are on each server ie... \\N123\W123456, \\N123\W123457 etc...., as we want to replace pc's below a certain spec.
That is, we want to find ALL current pc's that exist on each server, and also return some basic info re: these pc's ie. PCName (Nodename), IP Address, CPU Speed, RAM Size etc......
Is there a way we can obtain a list of ALL pc's on a Server ?
Regards
PJE
We have a Network running a Hundred or so Servers (All running Win2000) over a single domain, ie. DOMAIN, with each Server having a name ie. N123, N124 etc...
There are a list of Servers that our area looks after (About 20).
We are wanting to conduct an audit on PC's that are on each server ie... \\N123\W123456, \\N123\W123457 etc...., as we want to replace pc's below a certain spec.
That is, we want to find ALL current pc's that exist on each server, and also return some basic info re: these pc's ie. PCName (Nodename), IP Address, CPU Speed, RAM Size etc......
Is there a way we can obtain a list of ALL pc's on a Server ?
Regards
PJE
ASKER
Tried code above, takes a very long time and then an error appears.
Is there a way I can test a specific server ie. N010
Is there a way I can test a specific server ie. N010
Hmmm, i dont have 60 machines here, but i do have 12, and I tested this and it worked fast and fine for me.
I added the NetErrorHandler to show any errors.
I added the NetErrorHandler to show any errors.
Hi,
What do you mean by 'PCs on a server'? If 'PCs' means computers (workstations) then they are in the domain not on a server.
Regards, Geo
What do you mean by 'PCs on a server'? If 'PCs' means computers (workstations) then they are in the domain not on a server.
Regards, Geo
Geol,
I think he means all the stations are Win2000 server machines.
Shane
I think he means all the stations are Win2000 server machines.
Shane
ASKER
We have a single Domain called SERVICE, which ALL pc's are connected to (About 10,000), each site has at least 1 server that belongs to this domain (Over 200 servers in total), then we have WORKSTATIONS within each site that have drives mapped to a Server (ie. F,G,H,I drives for all WORKSTATIONS at Site 1 are mapped to N001, drives for all WORKSTATIONS at Site 2 are mapped to N002 etc....), these WORKSTATIONS are physically located within the same site as the server and therefore connected to this server, each site is then connected to external sites (Head Office Servers) via routers etc....
I basically want to get PC Names (Nodenames) for ALL WORKSTATIONS within a given site. The DOMAIN has too many pc's (10,000+) connected, and too many servers to scan. We only look after 20 odd servers (out of a possible 200+), and therefore ONLY want to get a list of WORKSTATIONS attached to SERVERS under our control.
Therefore, if I selected N001 as the server, ALL WORKSTATIONS connected to this server would be displayed. This could possibly be done by scanning IP Addresses in a SUBNET or Gateway ie.
N001 = Gateway[1] = '123.165.131'
Gateway[2] = '123.165.132'
For A:=1 to Gateway.Count
For I:=1 to 255
IP:=Gateway[A]+IntToStr(I)
// Get Nodename for IP - Code here
End;
End;
ps. ALL workstations and Servers are currently running Windows 2000
Hope this clears up problem
I basically want to get PC Names (Nodenames) for ALL WORKSTATIONS within a given site. The DOMAIN has too many pc's (10,000+) connected, and too many servers to scan. We only look after 20 odd servers (out of a possible 200+), and therefore ONLY want to get a list of WORKSTATIONS attached to SERVERS under our control.
Therefore, if I selected N001 as the server, ALL WORKSTATIONS connected to this server would be displayed. This could possibly be done by scanning IP Addresses in a SUBNET or Gateway ie.
N001 = Gateway[1] = '123.165.131'
Gateway[2] = '123.165.132'
For A:=1 to Gateway.Count
For I:=1 to 255
IP:=Gateway[A]+IntToStr(I)
// Get Nodename for IP - Code here
End;
End;
ps. ALL workstations and Servers are currently running Windows 2000
Hope this clears up problem
OK. I got the picture. If, for instance, every one of your sites (a server and its workstations) belongs to a different subnet then it probably could be done. Is this true? What I mean is:
site subnet
site1 123.165.131.0/24 (server=123.165.131.1; WS1=123.165.131.2; WS2=123.165.131.3; etc.)
site2 123.165.132.0/24
etc.
And you have a list of IP addresses (or computer names) of these 20 or so servers you are interested in.
Regards, Geo
site subnet
site1 123.165.131.0/24 (server=123.165.131.1; WS1=123.165.131.2; WS2=123.165.131.3; etc.)
site2 123.165.132.0/24
etc.
And you have a list of IP addresses (or computer names) of these 20 or so servers you are interested in.
Regards, Geo
ASKER
Basically yes
Regards
PJE
Regards
PJE
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Geo,
copied your code (cut and paste, so as not to make any mistakes), also created a servers.txt file.
Appears to work well, BUT, if the IP Address does not exist then process appears to take forever.
Is there something that can be done to speed up this problem ie. Timeout after a quicker period, or return a N/A if time exceeds a certain period etc....
I have tried setting a Minimim and Maximum rather than scanning from x to 255 (therefore for i = Min to Max), and this appears to work better, BUT, how do I determine the Minimum and Maximum IP Addresses for each server, if these are NOT know.
Regards
PJE
copied your code (cut and paste, so as not to make any mistakes), also created a servers.txt file.
Appears to work well, BUT, if the IP Address does not exist then process appears to take forever.
Is there something that can be done to speed up this problem ie. Timeout after a quicker period, or return a N/A if time exceeds a certain period etc....
I have tried setting a Minimim and Maximum rather than scanning from x to 255 (therefore for i = Min to Max), and this appears to work better, BUT, how do I determine the Minimum and Maximum IP Addresses for each server, if these are NOT know.
Regards
PJE
Hi,
I already said that:
>// you may speed up the process significantly here by pinging the sIP first and if the ping is successful then ask for the name
gethostbyaddr doesn't take forever but long enough for a single IP which doesn't exist. There are a lot of PING examples here in EE. Here is one of them using Indy's TIdcmClient component:
1. Drop one on your form
2. Add OnReply event of the TIdcmClient component:
procedure TForm1.IdIcmpClient1Reply( ASender: TComponent;
const AReplyStatus: TReplyStatus);
begin
if AReplyStatus.BytesReceived > 0 then begin
PingFlag := true;
end else begin
PingFlag := false;
end;
end;
3. In unit2 add a variable in the interface section:
var
PingFlag: boolean;
4. Change EnumWS function like:
....
IdIcmpClient1.ReceiveTimeo ut := 1000; // waiting one second per IP // <-- added
for i := k + 1 to 255 do begin
sIP := IP + IntToStr(i);
IdIcmpClient1.Host := sIP; // <-- added
IdIcmpClient1.Ping; // <-- added
if PingFlag then begin // <-- added
s := GetRemoteHostName(sIP);
if s <> '' then begin
List.Add(s + ' ' + sIP);
end;
end; // <-- added
end;
...
Regards, Geo
I already said that:
>// you may speed up the process significantly here by pinging the sIP first and if the ping is successful then ask for the name
gethostbyaddr doesn't take forever but long enough for a single IP which doesn't exist. There are a lot of PING examples here in EE. Here is one of them using Indy's TIdcmClient component:
1. Drop one on your form
2. Add OnReply event of the TIdcmClient component:
procedure TForm1.IdIcmpClient1Reply(
const AReplyStatus: TReplyStatus);
begin
if AReplyStatus.BytesReceived
PingFlag := true;
end else begin
PingFlag := false;
end;
end;
3. In unit2 add a variable in the interface section:
var
PingFlag: boolean;
4. Change EnumWS function like:
....
IdIcmpClient1.ReceiveTimeo
for i := k + 1 to 255 do begin
sIP := IP + IntToStr(i);
IdIcmpClient1.Host := sIP; // <-- added
IdIcmpClient1.Ping; // <-- added
if PingFlag then begin // <-- added
s := GetRemoteHostName(sIP);
if s <> '' then begin
List.Add(s + ' ' + sIP);
end;
end; // <-- added
end;
...
Regards, Geo
ASKER
Geo,
thanks for help, will have to try the last bit when I get back to work Next Tuesday (as it is a long weekend).
Regards
PJE
thanks for help, will have to try the last bit when I get back to work Next Tuesday (as it is a long weekend).
Regards
PJE
Thanks for the points. It will be a long weekend to me also (Orthodox Easter).
Just an idea: you could change the ping timeout to be a parameter entered by the user (in milliseconds) because for a single subnet with small amount of workstations (20 for instance) it will take 240 seconds to scan the whole range of 255 IP addresses. If your network is fast enough you may decrease this period to 100 seconds setting the timeout to 400 ms (or less). There is a risk of omiting some slow WSs in that case though.
There is also a possibility to stop the scan after several (let say 10) not found IPs in a row if you can be sure that workstations have consecutive IPs.
Regards, Geo
Just an idea: you could change the ping timeout to be a parameter entered by the user (in milliseconds) because for a single subnet with small amount of workstations (20 for instance) it will take 240 seconds to scan the whole range of 255 IP addresses. If your network is fast enough you may decrease this period to 100 seconds setting the timeout to 400 ms (or less). There is a risk of omiting some slow WSs in that case though.
There is also a possibility to stop the scan after several (let say 10) not found IPs in a row if you can be sure that workstations have consecutive IPs.
Regards, Geo
ASKER
Geo,
A couple of minor mods, and all works well.
Much appreciated
PJE
A couple of minor mods, and all works well.
Much appreciated
PJE
The pleasure was mine :-)
ASKER
Geo,
Is there any way to get PC details from the PC Names returned. In particular, CPU and RAM specs.
Happy to post another question with points.
As I initially mentioned, we are conducting an audit on PC's and want to find pc's below a certain spec, so that they can be replaced
Regards
PJE
Is there any way to get PC details from the PC Names returned. In particular, CPU and RAM specs.
Happy to post another question with points.
As I initially mentioned, we are conducting an audit on PC's and want to find pc's below a certain spec, so that they can be replaced
Regards
PJE
ASKER
Geo,
I may have found a way using msinfo32, but open to any other suggestions
Regards
PJE
I may have found a way using msinfo32, but open to any other suggestions
Regards
PJE
ASKER
HELP,
we have asked a particular site to turn on every pc in the building.
When I run my utility a certain number of pc's are displayed. I thought great all pc's have been found.
We then compared this list against an old list we had, and found that a number of pc's existed in the OLD list, which did not appear in the NEW LIST. So we pinged these pc's and sure enough they existed.
I then ran my utility again, and the pc's appeared, BUT others had disappeared.
It appears that everytime I run the UTILITY, the list changes (may be slightly).
What should I do, possibly increase my TIMEOUT value ???
Regards
PJE
we have asked a particular site to turn on every pc in the building.
When I run my utility a certain number of pc's are displayed. I thought great all pc's have been found.
We then compared this list against an old list we had, and found that a number of pc's existed in the OLD list, which did not appear in the NEW LIST. So we pinged these pc's and sure enough they existed.
I then ran my utility again, and the pc's appeared, BUT others had disappeared.
It appears that everytime I run the UTILITY, the list changes (may be slightly).
What should I do, possibly increase my TIMEOUT value ???
Regards
PJE
Hi,
Sorry for the delay. I got a week off and went on a vacation (without any computers there :-)
Yes, perhaps you should increase the timeout. As I said earlier using a short timeout some computers with slow connections may not be found. You could be changing the timeout dynamically also:
- first ping a particular IP using 200 ms for instance (depending on your network speed it might be from 100 to 500 ms);
- if the IP doesn't answer then try with 1000 ms for instance (or more);
- if there is no answer again consider that IP as not found.
Regards, Geo
Sorry for the delay. I got a week off and went on a vacation (without any computers there :-)
Yes, perhaps you should increase the timeout. As I said earlier using a short timeout some computers with slow connections may not be found. You could be changing the timeout dynamically also:
- first ping a particular IP using 200 ms for instance (depending on your network speed it might be from 100 to 500 ms);
- if the IP doesn't answer then try with 1000 ms for instance (or more);
- if there is no answer again consider that IP as not found.
Regards, Geo
Create a new application, & place a TMemo on the main form.
This example iterates all the computers on the net and adds them to memo
Shane
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure NetErrorHandler( dwResult : DWORD; const Msg : String);
procedure DisplayStruct(lpnr : PNETRESOURCE);
function EnumerateFunc(lpnr : PNETRESOURCE) : Boolean;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.NetErrorHandler(
dwResult : DWORD;
const Msg : String);
begin
Application.MessageBox(PCh
end;
procedure TForm1.DisplayStruct(lpnr : PNETRESOURCE);
var
p : PChar;
begin
p := lpnr^.lpRemoteName;
if (p[0] = '\') and (p[1] = '\') then
p := p + 2;
memo1.lines.Add(p);
Caption := IntToStr(memo1.lines.Count
end;
function TForm1.EnumerateFunc(lpnr : PNETRESOURCE) : Boolean;
var
dwResult : DWORD;
dwResultEnum : DWORD;
hEnum : THandle;
cbBuffer : DWORD; // 16K is a good size
cEntries : DWORD; // enumerate all possible entries
lpnrLocal : PNETRESOURCE; // pointer to enumerated structures
PtrResource : PNetResource;
i : DWORD;
begin
cbBuffer := 16384;
cEntries := DWORD(-1);
if Application.Terminated then begin
Result := FALSE;
Exit;
end;
dwResult := WNetOpenEnum(RESOURCE_GLOB
RESOURCETYPE_ANY,
RESOURCEUSAGE_CONTAINER, // enumerate allresources
lpnr, // NULL first timethis function is called
hEnum); // handle to resource
if dwResult <> NO_ERROR then begin
NetErrorHandler(dwResult, 'WNetOpenEnum');
Result := FALSE;
Exit;
end;
repeat
// Allocate memory for NETRESOURCE structures.
GetMem(lpnrLocal, cbBuffer);
dwResultEnum := WNetEnumResource(hEnum, // resource handle
cEntries, // defined locally as0xFFFFFFFF
lpnrLocal, // LPNETRESOURCE
cbBuffer); // buffer size
if dwResultEnum = NO_ERROR then begin
for i := 0 to cEntries - 1 do begin
PtrResource := PNETRESOURCE(PChar(lpnrLoc
if PtrResource^.dwDisplayType
DisplayStruct(PtrResource)
Application.ProcessMessage
// If this NETRESOURCE is a container, call the function
// recursively.
if (RESOURCEUSAGE_CONTAINER = (PtrResource^.dwUsage and RESOURCEUSAGE_CONTAINER)) and
(PtrResource^.dwDisplayTyp
if (not EnumerateFunc(PtrResource)
// TextOut(HandleDC, 10, 10, 'EnumerateFunc returned FALSE.', 29);
end;
end;
end;
end
else if dwResultEnum <> ERROR_NO_MORE_ITEMS then begin
NetErrorHandler(dwResultEn
break;
end;
until dwResultEnum = ERROR_NO_MORE_ITEMS;
FreeMem(lpnrLocal);
dwResult := WNetCloseEnum(hEnum);
if dwResult <> NO_ERROR then begin
NetErrorHandler(dwResult, 'WNetCloseEnum');
Result := FALSE;
Exit;
end;
Result := TRUE;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
EnumerateFunc(nil);
end;
end.