如何在程序中动态取得"网络邻居"中的工作组及计算机名?(100分)

A

arfei

Unregistered / Unconfirmed
GUEST, unregistred user!
我想在自己的程序中添加一个动态搜寻"网络邻居"中的工作组及计算机名的功能.
我找到了API中的WNet*@# 之类的函数,可里面的几个函数好象在绕弯子,彼此依赖,加上我也是最近才涉足局域网,清大伙指教.
最好有例程,一小段即可.
 
到这个网址去下载个控件,另外几个也都是可以的,
或者直接用,或者研究一下代码.

总之这种功能得通过ShellAPI实现.

http://members.aye.net/cgi-bin/dfs_components.cgi?browsedr
 
dwwang,横, 我的一个答案因为太大帖不上来,你的动作到很快啊 :))
只好到夜里了再帖了 *_*
 
确实是一个好题目,这个问题如果用 SHELLAPI 使用ISHELL接口去做很麻烦
正好我自己整理的BORLAND NEWS (news server: forums.borland.com)
新闻组阅读笔记中有一个很好的解答,借花献佛, 应该可以帮你.



问: How can I get the contents of the Neighborhood?
(如何能得到网络邻居的内容)


答1: (Scott Samet)
If you're asking how to get list of items in the Network Neighborhood,
it's a very complex task.
如果你问如何能得到网络邻居的列表,那是一个非常复杂的任务
you'll have to work with some very unfriendly OLE
objects.
您将不得不和非常不友好的OLE对象打交道


答2:
It's not as bad as Scott Samet says - but he's right anyhow :)
事情并非象SCOTT Samet 说的那么糟糕,但是他还是对的.

Below is two procedures you may be able to use .
下面两个过程可能会对你有用

procedure GetDomainList(TV:TTreeView);
var
a : Integer;
ErrCode : Integer;
NetRes : Array[0..1023] of TNetResource;
EnumHandle : THandle;
EnumEntries : DWord;
BufferSize : DWord;
s : string;
itm : TTreeNode;
begin
{ Start here }
try
With NetRes[0] do begin
dwScope :=RESOURCE_GLOBALNET;
dwType :=RESOURCETYPE_ANY;
dwDisplayType :=RESOURCEDISPLAYTYPE_DOMAIN;
dwUsage :=RESOURCEUSAGE_CONTAINER;
lpLocalName :=NIL;
lpRemoteName :=NIL;
lpComment :=NIL;
lpProvider :=NIL;
end;
{ get net root }
ErrCode:=WNetOpenEnum(
RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
RESOURCEUSAGE_CONTAINER,
@NetRes[0],
EnumHandle
);
If ErrCode=NO_ERROR then begin
EnumEntries:=1;
BufferSize:=SizeOf(NetRes);
ErrCode:=WNetEnumResource(
EnumHandle,
EnumEntries,
@NetRes[0],
BufferSize
);
WNetCloseEnum(EnumHandle);
ErrCode:=WNetOpenEnum(
RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
RESOURCEUSAGE_CONTAINER,
@NetRes[0],
EnumHandle
);
EnumEntries:=1024;
BufferSize:=SizeOf(NetRes);
ErrCode:=WNetEnumResource(
EnumHandle,
EnumEntries,
@NetRes[0],
BufferSize
);
IF ErrCode=No_Error then with TV do try
a:=0;
Items.BeginUpDate;
Items.Clear;
Itm:=Items.Add(TV.Selected,string(NetRes[0].lpProvider));
Itm.ImageIndex:=0;
Itm.SelectedIndex:=0;

{ get domains }
While a<enumEntries do with NetRes[a] do begin
s:=lpRemoteName;
Itm:=Items.AddChild(Items[0],S);
Itm.ImageIndex:=1;
Itm.SelectedIndex:=1;
inc(a);
end;
finally
Items.EndUpdate;
end;
end;
finally
WNetCloseEnum(EnumHandle);
end;
end;

procedure GetServerList(TV:TTreeView;Node:TTreeNode);
var
a : Integer;
ErrCode : Integer;
NetRes : Array[0..1023] of TNetResource;
EnumHandle : THandle;
EnumEntries : DWord;
BufferSize : DWord;
s : string;
itm : TTreeNode;
begin
If not Node.HasChildren then try
Screen.Cursor:=crHourglass;
With NetRes[0] do begin
dwScope :=RESOURCE_GLOBALNET;
dwType :=RESOURCETYPE_ANY;
dwDisplayType :=RESOURCEDISPLAYTYPE_generic;
dwUsage :=RESOURCEUSAGE_CONTAINER;
lpLocalName :=NIL;
lpRemoteName :=pChar(Tv.Selected.Text);
lpComment :=NIL;
lpProvider :=NIL;
end;
ErrCode:=WNetOpenEnum(
RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
RESOURCEUSAGE_CONTAINER,
@NetRes[0],
EnumHandle
);
If ErrCode=NO_ERROR then begin
EnumEntries:=1023;
BufferSize:=SizeOf(NetRes);
ErrCode:=WNetEnumResource(
EnumHandle,
EnumEntries,
@NetRes[0],
BufferSize
);
IF ErrCode=No_Error then with TV do try
a:=0;
Items.BeginUpdate;
While a<enumEntries do with NetRes[a] do begin
s:=lowercase(lpRemoteName);
Delete(s,1,2); { Delete leading "/" }
itm:=Items.AddChild(node,s);
itm.selectedIndex:=2;
itm.imageindex :=2;
inc(a);
end;
finally
Node.expand(false);
Items.EndUpdate;
end;
End;
finally
Screen.Cursor:=crDefault;
WNetCloseEnum(EnumHandle);
end;
end;


答3:(Scott Samet)
I was thinking of using the IShellFolder interface to walk the whole
Network Neighborhood namespace. Does the code you posted get all the
machines, and allow you to drill down into all the drives and shares?
If so, it's a whole lot shorter than using IShellFolder.
我的意思是使用IShellFolder接口查找整个"网络邻居". 您帖的代码是否能得到所有的机器名?
并且允许你处理所有的驱动器和共享吗? 如果是那样的话,要比使用ISHELLFOLDER简单多了

答4:> How can I get the contents of the Neighborhood?

The following unit defines a component, TNetworkBrowser, which can be used
to enumerate all resources on the network in a hierarchical tree. The
actual browsing takes a long time (try opening "Entire Network" in Windows
Explorer). If you set the Scope property to nsContext, you'll see the list
of machines from the "Network Neighborhood" window.
下面的一个单元定义了一个组件. TNetworkBrowser, 可以枚举hierachical树上所有
的网络资源. 实际上浏览是要花费很长时间的,这您可以通过在WINDOWS资源管理器
中打开"整个网络" 来比较一下. 如果你设置SCOPE属性 为nsContext , 你就可以看到
和网络邻居中一样的机器列表

Yorai Aminov
El-On Software Systems

unit NetBrwsr;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TNetScope = (nsConnected, nsGlobal, nsRemembered, nsContext);
TNetResourceType = (nrAny, nrDisk, nrPrint);
TNetDisplay = (ndDomain, ndGeneric, ndServer, ndShare, ndFile, ndGroup,
ndNetwork, ndRoot, ndShareAdmin, ndDirectory, ndTree, ndNDSContainer);
TNetUsage = set of (nuConnectable, nuContainer);

TNetworkItems = class;

TNetworkItem = class
private
FScope: TNetScope;
FResourceType: TNetResourceType;
FDisplay: TNetDisplay;
FUsage: TNetUsage;
FLocalName: string;
FRemoteName: string;
FComment: string;
FProvider: string;
FSubItems: TNetworkItems;
public
constructor Create;
destructor Destroy; override;
property Scope: TNetScope read FScope;
property ResourceType: TNetResourceType read FResourceType;
property Display: TNetDisplay read FDisplay;
property Usage: TNetUsage read FUsage;
property LocalName: string read FLocalName;
property RemoteName: string read FRemoteName;
property Comment: string read FComment;
property Provider: string read FProvider;
property SubItems: TNetworkItems read FSubItems;
end;

TNetworkItems = class
private
FList: TList;
procedure SetItem(Index: Integer; Value: TNetworkItem);
function GetItem(Index: Integer): TNetworkItem;
function GetCount: Integer;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure Add(Item: TNetworkItem);
procedure Delete(Index: Integer);
property Items[Index: Integer]: TNetworkItem read GetItem write
SetItem; default;
property Count: Integer read GetCount;
end;

TNetworkBrowser = class(TComponent)
private
FItems: TNetworkItems;
FScope: TNetScope;
FResourceType: TNetResourceType;
FUsage: TNetUsage;
FActive: Boolean;
procedure Refresh;
procedure SetActive(Value: Boolean);
procedure SetScope(Value: TNetScope);
procedure SetResourceType(Value: TNetResourceType);
procedure SetUsage(Value: TNetUsage);
procedure EnumerateNet(NetItems: TNetworkItems; lpnr: PNetResource);
protected
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Open;
procedure Close;
property Items: TNetworkItems read FItems;
published
property Scope: TNetScope read FScope write SetScope default nsGlobal;
property ResourceType: TNetResourceType read FResourceType
write SetResourceType default nrAny;
property Usage: TNetUsage read FUsage write SetUsage default [];
property Active: Boolean read FActive write SetActive default False;
end;

implementation

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

{ TNetworkItem }

constructor TNetworkItem.Create;
begin
inherited;
FSubItems := TNetworkItems.Create;
end;

destructor TNetworkItem.Destroy;
begin
if FSubItems <> nil then
FSubItems.Free;
inherited;
end;

{ TNetworkItems }

constructor TNetworkItems.Create;
begin
inherited;
FList := TList.Create;
end;

destructor TNetworkItems.Destroy;
begin
Clear;
if FList <> nil then
FList.Free;
inherited;
end;

procedure TNetworkItems.SetItem(Index: Integer; Value: TNetworkItem);
begin
if (FList.Items[Index] <> nil) and (FList.Items[Index] <> Value) then
TNetworkItem(FList.Items[Index]).Free;
FList.Items[Index] := Value;
end;

function TNetworkItems.GetItem(Index: Integer): TNetworkItem;
begin
Result := TNetworkItem(FList.Items[Index]);
end;

procedure TNetworkItems.Clear;
begin
while Count > 0 do
Delete(0);
end;

procedure TNetworkItems.Add(Item: TNetworkItem);
begin
FList.Add(Item);
end;

procedure TNetworkItems.Delete(Index: Integer);
begin
if FList.Items[Index] <> nil then
TNetworkItem(FList.Items[Index]).Free;
FList.Delete(Index);
end;

function TNetworkItems.GetCount: Integer;
begin
if FList <> nil then
Result := FList.Count
else
Result := 0;
end;

{ TNetworkBrowser }

constructor TNetworkBrowser.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItems := TNetworkItems.Create;
FScope := nsGlobal;
FResourceType := nrAny;
FUsage := [];
end;

destructor TNetworkBrowser.Destroy;
begin
if FItems <> nil then
FItems.Free;
inherited;
end;

procedure TNetworkBrowser.EnumerateNet(NetItems: TNetworkItems; lpnr:
PNetResource);
var
dwResult, dwResultEnum: Integer;
hEnum: THandle;
cbBuffer, cEntries, i: Integer;
nrArray: PNetResourceArray;
NewItem: TNetworkItem;
dwScope, dwType, dwUsage: Integer;
begin
cbBuffer := 16384;
cEntries := $FFFFFFFF;

case FScope of
nsConnected: dwScope := RESOURCE_CONNECTED;
nsGlobal: dwScope := RESOURCE_GLOBALNET;
nsRemembered: dwScope := RESOURCE_REMEMBERED;
nsContext: dwScope := RESOURCE_CONTEXT;
else
dwScope := RESOURCE_GLOBALNET;
end;
case FResourceType of
nrAny: dwType := RESOURCETYPE_ANY;
nrDisk: dwType := RESOURCETYPE_DISK;
nrPrint: dwType := RESOURCETYPE_PRINT;
else
dwType := RESOURCETYPE_ANY;
end;
dwUsage := 0;
if nuConnectable in FUsage then
dwUsage := dwUsage or RESOURCEUSAGE_CONNECTABLE;
if nuContainer in FUsage then
dwUsage := dwUsage or RESOURCEUSAGE_CONTAINER;

dwResult := WNetOpenEnum(dwScope, dwType, dwUsage, lpnr, hEnum);
if dwResult <> NO_ERROR then Exit;

GetMem(nrArray, cbBuffer);
repeat
dwResultEnum := WNetEnumResource(hEnum, cEntries, nrArray, cbBuffer);
if dwResultEnum = NO_ERROR then
for i := 0 to cEntries-1 do
begin
NewItem := TNetworkItem.Create;
case nrArray.dwScope of
RESOURCE_CONNECTED: NewItem.FScope := nsConnected;
RESOURCE_GLOBALNET: NewItem.FScope := nsGlobal;
RESOURCE_REMEMBERED: NewItem.FScope := nsRemembered;
RESOURCE_CONTEXT: NewItem.FScope := nsContext;
else
NewItem.FScope := nsGlobal;
end;
case nrArray.dwType of
RESOURCETYPE_ANY: NewItem.FResourceType := nrAny;
RESOURCETYPE_DISK: NewItem.FResourceType := nrDisk;
RESOURCETYPE_PRINT: NewItem.FResourceType := nrPrint;
else
NewItem.FResourceType := nrAny;
end;
case nrArray.dwDisplayType of
RESOURCEDISPLAYTYPE_GENERIC: NewItem.FDisplay := ndGeneric;
RESOURCEDISPLAYTYPE_DOMAIN: NewItem.FDisplay := ndDomain;
RESOURCEDISPLAYTYPE_SERVER: NewItem.FDisplay := ndServer;
RESOURCEDISPLAYTYPE_SHARE: NewItem.FDisplay := ndShare;
RESOURCEDISPLAYTYPE_FILE: NewItem.FDisplay := ndFile;
RESOURCEDISPLAYTYPE_GROUP: NewItem.FDisplay := ndGroup;
RESOURCEDISPLAYTYPE_NETWORK: NewItem.FDisplay := ndNetwork;
RESOURCEDISPLAYTYPE_ROOT: NewItem.FDisplay := ndRoot;
RESOURCEDISPLAYTYPE_SHAREADMIN: NewItem.FDisplay :=
ndShareAdmin;
RESOURCEDISPLAYTYPE_DIRECTORY: NewItem.FDisplay :=
ndDirectory;
RESOURCEDISPLAYTYPE_TREE: NewItem.FDisplay := ndTree;
RESOURCEDISPLAYTYPE_NDSCONTAINER: NewItem.FDisplay :=
ndNDSContainer;
else
NewItem.FDisplay := ndGeneric;
end;
NewItem.FUsage := [];
if nrArray.dwUsage and RESOURCEUSAGE_CONNECTABLE <> 0 then
Include(NewItem.FUsage, nuConnectable);
if nrArray.dwUsage and RESOURCEUSAGE_CONTAINER <> 0 then
Include(NewItem.FUsage, nuContainer);
NewItem.FLocalName := StrPas(nrArray.lpLocalName);
NewItem.FRemoteName := StrPas(nrArray.lpRemoteName);
NewItem.FComment := StrPas(nrArray.lpComment);
NewItem.FProvider := StrPas(nrArray.lpProvider);
NetItems.Add(NewItem);
// if container, call recursively
if (nuContainer in NewItem.FUsage) and (FScope <> nsContext) then
EnumerateNet(NewItem.FSubItems, @nrArray)
end;
until dwResultEnum = ERROR_NO_MORE_ITEMS;

FreeMem(nrArray);
WNetCloseEnum(hEnum);
end;

procedure TNetworkBrowser.Refresh;
begin
FItems.Clear;
if FActive then
EnumerateNet(FItems, nil);
end;

procedure TNetworkBrowser.SetActive(Value: Boolean);
begin
if Value <> FActive then
begin
FActive := Value;
Refresh;
end;
end;

procedure TNetworkBrowser.SetScope(Value: TNetScope);
begin
if Value <> FScope then
begin
FScope := Value;
Refresh;
end;
end;

procedure TNetworkBrowser.SetResourceType(Value: TNetResourceType);
begin
if Value <> FResourceType then
begin
FResourceType := Value;
Refresh;
end;
end;

procedure TNetworkBrowser.SetUsage(Value: TNetUsage);
begin
if Value <> FUsage then
begin
FUsage := Value;
Refresh;
end;
end;

procedure TNetworkBrowser.Open;
begin
Active := True;
end;

procedure TNetworkBrowser.Close;
begin
Active := False;
end;

end.
 
你知道我为什么快吗?就是因为我从来不贴大段代码 :)

我希望大家还是尽量不要贴大段代码,否则速度慢的时候
很难读完,影响交流。有这种需求,可以写e-mail,只要
真正解决问题,大家也不会怀疑为什么分数会给你吧! *_^

言归正传,我说的那个网址,实际上有多个构件,可以实现
包含本题在内的各种功能,已经形成了一套比较完整的体系,
调用起来也很方便,不妨参考一下。
 
荷荷,dwwang老兄,我是自学的计算机和DELPHI,从没人教我什么,到现在为止
也是一个人在做开发. 我深知实际上很多人到网上来求医问药都是应急,而且一般
都很急,大家都忙啊。所以需要的是一个实在的解决方案,代码是最合适的
这也就是我一直坚持只要不麻烦就一定写出代码来答问题的原因.

道理对好手来说,是画龙点睛,一句就透。可还有些朋友不太懂,一句话又讲不明白
的,不如写些代码帮人家先把问题解决。西西。

对了,你说的那个网址我去过了,挺好的。 Thanks. ^_^
best regards!
 
对不起,最近网慢如蜗牛,国外简直去不了!
王寒松老兄的意见深得我心,一百大洋归你了!
 
如何判断我的工作站是否在局域网上,(随时判断,如断线立即提示)
 
我也正在找如何搜索局域网的信息的代码,看来我搜索到了。
就如上面的仁兄说的,很多人问问题就是为了急用,说了一大段道理,可能提问者不一定理解了
写段可行的代码,适当的写些注解,我想这个很有帮助了。如果看不懂代码,可以继续问了。
不耻下问了。
当然,能多给别人帮助,也是一种快乐了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
顶部