充分利用局域網中的共享資源,無疑將減少用戶的硬件和軟件投資。在我們的程序中,常常會需要列舉局域網絡中的共享資源,如在MIDAS多層應用程序中可能要選擇上層應用程序所在的服務器的名稱、在打印模塊中選擇可用的網絡打印機、在應用程序中選擇其它機器上的共享文件等。
以一個MIDAS三層數據庫應用程序為例子,我們可以用DELPHI制作一個客戶端應用程序和一個中間層業務處理程序,由中間層業務處理程序向數據庫存取數據,再將結果反饋到客戶端。當客戶端應用程序與中間層程序和數據庫服務程序不在一台機器上時,需要指定中間層程序和數據庫服務程序所在的服務器的名稱。
在DELPHI程序中,我們可以通過WIN API來列舉局域網絡中的服務器名稱、用戶計算機名稱、用戶共享目錄和文件、共享打印機等資源,這些API由文件MPR.DLL提供。
下面以WIN9X的對等網絡為例子,列舉“網絡鄰居”中的工作組名稱、用戶計算機名稱、共享目錄和文件、共享打印機等資源。
一、列舉“網絡鄰居”中的工作組名稱
在“網絡鄰居”中,打開“整個網絡”,可以看到網絡中的所有工作組的名稱。在DELPHI程序中,可以用API函數WNetOpenEnum和WNetEnumResource來列舉“網絡鄰居”中的工作組名稱。
下面是兩個API函數的簡介,具體請參見DELPHI幫助文件。
//WNetOpenEnum用於獲取一個網絡資源句柄,作為WNetEnumResource列舉網絡資源的依據,其函數原型如下:
function WNetOpenEnum(
dwScope,//網絡范圍,RESOURCE_CONNECTED(已連接機器),RESOURCE_GLOBALNET(所有機器),
RESOURCE_REMEMBERED(已記憶的機器)
dwType,//資源類型,RESOURCETYPE_ANY(所有資源),RESOURCETYPE_DISK(文件資源),
RESOURCETYPE_PRINT(打印資源)
dwUsage//資源用途,0(所有資源),RESOURCEUSAGE_CONNECTABLE(所有可連接資源),
RESOURCEUSAGE_CONTAINER(所有container資源)僅在dwScope為RESOURCE_GLOBALNET是有效: DWord;
lpNetResource: PNetResource;//NetResource類型指針,其內存表示網絡資源的層次,為NIL時
表示最上層,僅在dwScope為RESOURCE_GLOBALNET時有效,其它情況時應為NIL
var lphEnum: THandle//返回網絡資源句柄,是WNetEnumResource進一步列舉網絡資源的依據
): DWord; stdcall;返回值NO_ERROR表示執行成功,否則應用GetLastError獲取錯誤信息
//WNetEnumResource用於列出當前網絡中可用的資源,包括文件資源和打印資源,其函數原型如下:
function WNetEnumResource(hEnum: THandle;//WNetEnumResource進一步列舉網絡資源的依據,通常由WNetOpenEnum取得var lpcCount: DWORD;//要取得資源的數目,$FFFFFFFF表示列出所有資源,返回值為實際資源數目lpBuffer: Pointer;//接收結果的緩沖區的指針,一般是NetResource類型的數組var lpBufferSize: DWORD//接收結果的緩沖區大小(Byte)): DWord; stdcall;返回值為NO_ERROR(執行成功)或ERROR_NO_MORE_ITEMS(資源列舉完畢),否則應用GetLastError獲取錯誤信息。
要列舉網絡中的工作組信息,首先要獲取網絡中的網絡類型,再獲取每一種類型網絡中包含的工作組的名稱。
1、獲取網絡類型信息
局域網中可以是由多種類型的網絡組成,如由Microsoft、Novell等類型的網絡組成。用API
函數WNetOpenEnum和WNetEnumResource可以獲取網絡類型信息。
(1)用WNetOpenEnum函數返回一個句柄,作為WNetEnumResource列舉網絡資源的依據。我們的目
標是列舉“整個網絡”的工作組名稱,因而網絡范圍為RESOURCE_GLOBALNET(所有機器)、資源類
型為RESOURCETYPE_DISK(文件資源)、資源用途為RESOURCEUSAGE_CONTAINER(所有container資源)、
網絡層次為最高層(NIL),這樣可以得到一個句柄,以便進一步列舉網絡資源。具體的程序段如下:
{ Res : DWord; lphEnum : THandle; }
Res := WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_CONTAINER, Nil,lphEnum);
If Res <> NO_ERROR Then exit;//執行失敗
(2)用API函數WNetEnumResource可以獲取網絡類型信息,此時要用到上面獲取的句柄lphEnum,
可以獲取一個NetResource類型的數組,每個NetResource元素即為一種網絡類型信息。
具體的請參見以下程序段及注釋信息。
type
TNetResourceArray = ^TNetResource;//網絡類型的數組
Var
NetResource : TNetResource;
Buf : Pointer;
Count,BufSize,Res : DWord;
lphEnum : THandle;
p : TNetResourceArray;
i,j : SmallInt;
NetworkTypeList : TList;begin
......
Count := $FFFFFFFF;//不限資源數目
BufSize := 8192;//緩沖區大小設置為8K
GetMem(Buf, BufSize);//申請內存,用於獲取工作組信息
Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);//獲取網絡類型信息
If ( Res = ERROR_NO_MORE_ITEMS )//資源列舉完畢
or (Res <> NO_ERROR )//執行失敗
Then Exit;
P := TNetResourceArray(Buf);
For I := 0 To Count - 1 Do//記錄各個網絡類型的信息
Begin
NetworkTypeList.Add(p);
Inc(P);
End;
......end;
2、獲取工作組信息
在獲取網絡類型信息後,可以根據此信息獲取此類型網絡中的服務器(工作組)信息。
在WNetOpenEnum函數中,將參數lpNetResource指定為一種網絡類型信息,可以獲取一個句柄,在WNetEnumResource中利用這個句柄,可以獲取一個NetResource類型的數組,每個NetResource元素的lpRemoteName部分即為一個工作組名稱(如“MyWorkGroup”)。
具體的請參見以下程序段及注釋信息。
//列出一個網絡類型中的所有工作組名稱
NetResource := TNetResource(NetworkTypeList.Items[J]^);//網絡類型信息//獲取某個網絡類型的文件資源的句柄,NetResource為網絡類型信息,lphEnum為返回句柄
Res := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_CONTAINER, @NetResource,lphEnum);
If Res <> NO_ERROR Then break;//執行失敗
While true Do//列舉一個網絡類型的所有工作組的信息
Begin
Count := $FFFFFFFF;//不限資源數目
BufSize := 8192;//緩沖區大小設置為8K
GetMem(Buf, BufSize);//申請內存,用於獲取工作組信息
//獲取一個網絡類型的文件資源信息,
Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);
If ( Res = ERROR_NO_MORE_ITEMS ) //資源列舉完畢
or (Res <> NO_ERROR) //執行失敗
then break;
P := TNetResourceArray(Buf);
For I := 0 To Count - 1 Do//列舉各個工作組的信息
Begin
List.Add( StrPAS( P^.lpRemoteName ));//取得一個工作組的名稱
Inc(P);
End;
End;
3、獲取工作組信息的完全源代碼//列舉出整個網絡中的工作組名稱,返回值為TRUE表示執行成功,
//參數List中返回服務器(工作組)的名稱
Function GetServerList( var List : TStringList ) : Boolean;
Var
NetResource : TNetResource;
Buf : Pointer;
Count,BufSize,Res : DWord;
lphEnum : THandle;
p : TNetResourceArray;
i,j : SmallInt;
NetworkTypeList : TList;
Begin
Result := False;
NetworkTypeList := TList.Create;
List.Clear;//獲取整個網絡中的文件資源的句柄,lphEnum為返回名柄
Res := WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_CONTAINER, Nil,lphEnum);
If Res <> NO_ERROR Then exit;//Raise Exception(Res);//執行失敗//獲取整個網絡中的網絡類型信息
Count := $FFFFFFFF;//不限資源數目
BufSize := 8192;//緩沖區大小設置為8K
GetMem(Buf, BufSize);//申請內存,用於獲取工作組信息
Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);
If ( Res = ERROR_NO_MORE_ITEMS )//資源列舉完畢
or (Res <> NO_ERROR )//執行失敗
Then Exit;
P := TNetResourceArray(Buf);
For I := 0 To Count - 1 Do//記錄各個網絡類型的信息
Begin
NetworkTypeList.Add(p);
Inc(P);
End;
//WNetCloseEnum關閉一個列舉句柄
Res := WNetCloseEnum(lphEnum);//關閉一次列舉
If Res <> NO_ERROR Then exit;
For J := 0 To NetworkTypeList.Count-1 Do //列出各個網絡類型中的所有工作組名稱
Begin//列出一個網絡類型中的所有工作組名稱
NetResource := TNetResource(NetworkTypeList.Items[J]^);//網絡類型信息//獲取某個網絡類型的文件資源的句柄,NetResource為網絡類型信息,lphEnum為返回名柄
Res := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_CONTAINER, @NetResource,lphEnum);
If Res <> NO_ERROR Then break;//執行失敗
While true Do//列舉一個網絡類型的所有工作組的信息
Begin
Count := $FFFFFFFF;//不限資源數目
BufSize := 8192;//緩沖區大小設置為8K
GetMem(Buf, BufSize);//申請內存,用於獲取工作組信息
//獲取一個網絡類型的文件資源信息,
Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);
If ( Res = ERROR_NO_MORE_ITEMS ) //資源列舉完畢
or (Res <> NO_ERROR) //執行失敗
then break;
P := TNetResourceArray(Buf);
For I := 0 To Count - 1 Do//列舉各個工作組的信息
Begin
List.Add( StrPAS( P^.lpRemoteName ));//取得一個工作組的名稱
Inc(P);
End;
End;
Res := WNetCloseEnum(lphEnum);//關閉一次列舉
If Res <> NO_ERROR Then break;//執行失敗
End;
Result := True;
FreeMem(Buf);
NetworkTypeList.Destroy;
End;
二、列舉一個工作組中的計算機名稱
在WNetOpenEnum函數中,將參數lpNetResource中的lpRemoteName部分指定為一個工作組的名稱(如“MyWorkGroup”),可以獲取一個句柄,在WNetEnumResource中利用這個句柄,可以獲取一個NetResource類型的數組,每個NetResource元素的lpRemoteName部分即為一個計算機名稱(如“wangfajun”)。
具體的請參見以下程序段及注釋信息。
NetResource.lpRemoteName := @GroupName[1];//指定工作組名稱
NetResource.dwDisplayType := RESOURCEDISPLAYTYPE_SERVER;//顯示類型為服務器(工作組)
NetResource.dwUsage := RESOURCEUSAGE_CONTAINER;
NetResource.dwScope := RESOURCETYPE_DISK;//列舉文件資源信息
//獲取指定工作組的網絡資源句柄
Res := WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_CONTAINER, @NetResource,lphEnum);
獲取計算機名稱的完全程序源代碼如下:
//列舉出指定工作組GroupName中的計算機名稱,返回值為TRUE表示執行成功,//參數List中返回計算機名稱Function GetUsers( GroupName : string; var List : TStringList ) : Boolean;Var
NetResource : TNetResource;
Buf : Pointer;
Count,BufSize,Res : DWord;
Ind : Integer;
lphEnum : THandle;
Temp : TNetResourceArray;
Begin
Result := False;
List.Clear;
FillChar(NetResource, SizeOf(NetResource), 0);//初始化網絡層次信息
NetResource.lpRemoteName := @GroupName[1];//指定工作組名稱
NetResource.dwDisplayType := RESOURCEDISPLAYTYPE_SERVER;//類型為服務器(工作組)
NetResource.dwUsage := RESOURCEUSAGE_CONTAINER;
NetResource.dwScope := RESOURCETYPE_DISK;//列舉文件資源信息
//獲取指定工作組的網絡資源句柄
Res := WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_CONTAINER, @NetResource,lphEnum);
If Res <> NO_ERROR Then Exit; //執行失敗
While True Do//列舉指定工作組的網絡資源
Begin
Count := $FFFFFFFF;//不限資源數目
BufSize := 8192;//緩沖區大小設置為8K
GetMem(Buf, BufSize);//申請內存,用於獲取工作組信息
//獲取計算機名稱
Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);
If Res = ERROR_NO_MORE_ITEMS Then break;//資源列舉完畢
If (Res <> NO_ERROR) then Exit;//執行失敗
Temp := TNetResourceArray(Buf);
For Ind := 0 to Count - 1 do//列舉工作組的計算機名稱
Begin
//獲取工作組的計算機名稱,+2表示刪除"",如wangfajun=>wangfajun
List.Add(Temp^.lpRemoteName + 2);
Inc(Temp);
End;
End;
Res := WNetCloseEnum(lphEnum);//關閉一次列舉
If Res <> NO_ERROR Then exit;//執行失敗
Result := True;
FreeMem(Buf);
End;
三、列舉一個計算機中的共享資源
在WNetOpenEnum函數中,將參數lpNetResource中的lpRemoteName部分指定為一個計算機的名稱(如“wangfajun”),可以獲取一個句柄,在WNetEnumResource中利用這個句柄,可以獲取一個NetResource類型的數組,每個NetResource元素的lpRemoteName部分即為計算機中的共享資源名稱(可以是共享目錄和文件名稱、共享打印機名稱等,如“wangfajun共享文件”)。
具體的請參見以下程序段及注釋信息。
NetResource.lpRemoteName := @UserName[1];//指定計算機名稱
//獲取指定計算機的網絡資源句柄
Res := WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_ANY,
RESOURCEUSAGE_CONNECTABLE, @NetResource,lphEnum);
獲取計算機名稱的完全程序源代碼如下:
//列舉出指定計算機UserName中的共享資源名稱,返回值為TRUE表示執行成功,//參數List中返回共享資源名稱Function GetUserResource( UserName : string ; var List : TStringList ) : Boolean;Var
NetResource : TNetResource;
Buf : Pointer;
Count,BufSize,Res : DWord;
Ind : Integer;
lphEnum : THandle;
Temp : TNetResourceArray;
Begin
Result := False;
List.Clear;
FillChar(NetResource, SizeOf(NetResource), 0);//初始化網絡層次信息
NetResource.lpRemoteName := @UserName[1];//指定計算機名稱
//獲取指定計算機的網絡資源句柄
Res := WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_ANY,
RESOURCEUSAGE_CONNECTABLE, @NetResource,lphEnum);
If Res <> NO_ERROR Then exit;//執行失敗
While True Do//列舉指定工作組的網絡資源
Begin
Count := $FFFFFFFF;//不限資源數目
BufSize := 8192;//緩沖區大小設置為8K
GetMem(Buf, BufSize);//申請內存,用於獲取工作組信息
//獲取指定計算機的網絡資源名稱
Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);
If Res = ERROR_NO_MORE_ITEMS Then break;//資源列舉完畢
If (Res <> NO_ERROR) then Exit;//執行失敗
Temp := TNetResourceArray(Buf);
For Ind := 0 to Count - 1 do
Begin
//獲取指定計算機中的共享資源名稱,+2表示刪除"",
//如wangfajun=>wangfajun
List.Add(Temp^.lpRemoteName + 2);
Inc(Temp);
End;
End;
Res := WNetCloseEnum(lphEnum);//關閉一次列舉
If Res <> NO_ERROR Then exit;//執行失敗
Result := True;
FreeMem(Buf);
End;