首页  编辑  

断开网络连接

Tags: /超级猛料/Network.网络通讯/LAN/   Date Created:

有的时候,即使访问一下某台机器,然后断开了,但是对方的机器在关闭系统前还是要弹出一个窗口进行警告!如何去掉呢?

在WINDOWS95&WINDOWS98下如何关闭网络连接

                                  黄 飞  <98/5/20>

一.问题提出:

每当你通过WINDOWS95或WINDOWS98访问"网上邻居"时,系统自动的建立了两

台机器之间的网络连接关系,但是在访问结束后,并不自动的断开网络连接,

所以有时我们关闭WINDOWS系统时,会弹出一个对话框,询问是否关闭网络连

接,在回答"YES"后,才真正开始关闭计算机.

程序员编制系统关闭程序时,就需要考虑这种情况,虽然SDK提供了关机的API:

ExitWindowsEx()和ExitWindows(),但实际应用中我发现,在指定FORCE关机时

在特定情况下会出问题.所以,必须想办法首先断开网络连接.

二.编程接口:

WINDOWS95及WINDOWS98提供的这方面的网络编程接口在SVRAPI.DLL中,利用它

我们可以列举出当前网络连接状态,控制或删除网络连接.WINDOWS附件中的

NETWATCH.EXE工具就是这样实现的.

也许您会问,NetAPI的详细说明在开发工具的SDK文档中很详细了,没有必要在

此演示.但是,在查寻了很多资料后,我不得不说:MSDN中有关NetAPI的部分说

明是错误的,至少是不完整而且含混不清的,可以说,依靠这些文档,你不能实

现全部的功能!下面的代码是本人自己分析得来,使用后,您会发现正确的应用

和文档说明有多么大的差距.

三.API声明:

关闭网络连接的实现方法分两步: 枚举出当前所有的网络连接状况; 依次

断开枚举出的网络连接.

1.枚举出当前所有的网络连接状况:

       依照开发帮助文档,这个API是这样的:

       NET_API_STATUS NetSessionEnum(

         LPWSTR servername,    

         LPWSTR UncClientName,  

         LPWSTR username,      

         DWORD level,          

         LPBYTE *bufptr,        

         DWORD prefmaxlen,      

         LPDWORD entriesread,  

         LPDWORD totalentries,  

         LPDWORD resume_handle  

       );

       但是,实际情况是,在WINDOWS95和WINDOWS98平台下,

       这样调用根本就无法连接上库文件.真正的API声明应该是:

       DWORD NetSessionEnum( LPSTR,

                             DWORD,

                             LPBYTE,

                             DWORD,

                             LPDWORD,

                             LPDWORD )

       参数1: NULL表示枚举本机的网络连接

       参数2: 不详.在枚举中是常量0x32.

       参数3: 存放信息的缓冲区指针

       参数4: 缓冲区长度

       参数5: 指向返回连接个数

       参数6: 指向总共连接个数

       可见,参数个数完全不同,另外参数意义也发生了变化.

2.依次断开枚举出的网络连接:

       还算幸运的是,断开网络连接的API声明是正确的:

       NET_API_STATUS NetSessionDel(

                 LPWSTR servername,    

                 LPWSTR UncClientName,  

                 LPWSTR username    );

       不过要注意的是,第2个和第3个参数的内容需要

       从枚举得到的缓冲区中去取.具体方法参见程序.

四.源代码:

以下是实现断开网络连接的子程序,你可以方便的把它们加入到自己的项目中

去,而不用和我一样浪费时间去研究到底怎样实现网络枚举了.

注:由于本程序只实际用到了一个SVRAPI.DLL中的函数声明,简便期间,我没有

用原有的头文件,自己定义一下就可以了.

///////////////////////////////////////////////////////////////////

// File:        NetClose.H

// Version:     1.01

#define NETBUFF_SIZE    0x208

#define NetSessionEnum_PROFILE  ( DWORD (__stdcall *) \

       ( LPSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD ) )

#define NetSessionDel_PROFILE   ( DWORD (__stdcall *) \

                               ( LPSTR, LPSTR, DWORD ) )

///////////////////////////////////////////////////////////////////

// File:        NetClose.CPP

// Version:     1.01

///////////////////////////////////////////////////////////////////

// Define:              BOOL NetCloseAll( VOID )

// Parameters:          None

// Return:              TRUE or FALSE

//

// Author:              Mr.Huang fei

// Time:                5/7/1998

// Note:                Can only be used on Windows95 & Windows98

// Remark:              Close all network connections

///////////////////////////////////////////////////////////////////

BOOL NetCloseAll( VOID )

{

       BYTE    byBuff[NETBUFF_SIZE];

       DWORD   dwNetRet                = 0;;

       DWORD   i                       = 0;

       DWORD   dwEntries               = 0;

       DWORD   dwTotalEntries          = 0;

       LPSTR   szClient                = NULL;

       DWORD   dwUserName              = 0;

       BOOL    bRet                    = FALSE;

       LPBYTE  lpbyBuff = (LPBYTE)byBuff;

       DWORD (__stdcall * hookNetSessionEnum)( LPSTR, DWORD, \

                               LPBYTE, DWORD, LPDWORD, LPDWORD );

       DWORD (__stdcall * hookNetSessionDel)( LPSTR, LPSTR, DWORD );

       HINSTANCE hMod = LoadLibrary( "SVRAPI.DLL" );

       if( hMod != NULL )

       {

               // Get the address of function

               hookNetSessionEnum = NetSessionEnum_PROFILE

                                    GetProcAddress

                                ( hMod, TEXT("NetSessionEnum") );

               hookNetSessionDel  = NetSessionDel_PROFILE

                                    GetProcAddress

                                ( hMod, TEXT("NetSessionDel") );

               if( ( hookNetSessionDel != NULL ) &&

                   ( hookNetSessionEnum != NULL ) )

               {

                       dwNetRet = hookNetSessionEnum(  NULL,

                                          0x32, byBuff,

                                          NETBUFF_SIZE, &dwEntries,

                                          &dwTotalEntries );

                       if( dwNetRet == 0 )

                       {

                           bRet = TRUE;

                           for( i=0; i < dwTotalEntries; i++ )

                           {

                             szClient = (LPSTR)(((DWORD *)

                                            lpbyBuff)[0]);

                             dwUserName = ((DWORD *)lpbyBuff)[2];

                             dwNetRet = hookNetSessionDel( NULL,

                                           szClient, dwUserName );

                             if( dwNetRet != 0 )

                             {

                                     bRet = FALSE;

                                     break;

                             }

                             lpbyBuff += 26;

                           }

                       } // NetSessionEnum(...)

                       else

                               bRet = FALSE;

               } // GetProcAddress(...)

               else

                       bRet = FALSE;

               FreeLibrary( hMod );

       } // LoadLibrary(...)

       return bRet;

}

五.总结:

以上是开发过程中的一点经验,希望对大家有所帮助,有不对的地方请谅解并

指出.另外,众所周知Microsoft的开发文档有相当一部分是未公开的,这些未

公开信息有时会给我们造成很大的困难,在此希望有类似体验的程序开发者

把自己的经验写出来,让后来者少走一些弯路.

************************

没有测试的。

const

 NETBUFF_SIZE = $208;

type

 NetSessionEnum = function(ServerName: LPSTR; Level: DWORD; Bufptr: PBYTE; MaxLen: DWORD; total: LPDWORD; resume_hwnd: LPDWORD): Dword; stdcall;

 NetSessionDel = function(ServerName: LPSTR; ClientName: LPSTR; UserName: LPSTR): dword; stdcall;

function NetCloseAll: Boolean;

type

 TbyBuff=array[0..NETBUFF_SIZE-1] of byte;

var

 byBuff:TBybuff;

 dwNetRet,i,dwEntries,dwTotalEntries:dword;

 szClient:LPSTR;

 dwUserName:LPSTR;

 bRet:boolean;

 lpbyBuff:^TbyBuff;

 h:hwnd;

 EnumProc:NetSessionEnum;

 DelProc:NetSessionDel;

begin

 h:=LoadLibrary('svrapi.dll');

 lpbybuff:=@bybuff;

 bRet:=false;

 if h<>0 then

 begin

   EnumProc:=GetProcAddress(h,'NetSessionEnum');

   DelProc:=GetprocAddress(h,'NetSessionDel');

   if Assigned(EnumProc) and Assigned(DelProc) then

   begin

     dwNetRet:=EnumProc(nil,$32,@byBuff,NETBUFF_SIZE,@dwEntries,@dwTotalEntries);

     if dwNetRet=0 then

     begin

       bRet:=true;

       for i:=0 to dwTotalEntries-1 do

       begin

         szClient:=LPSTR(lpbybuff^[0]);

         dwUserName:=LPSTR(LPbybuff^[2]);

         dwNetRet:=DelProc(nil,szClient,dwUserName);

         if dwNetRet<>0 then

         begin

           bRet:=false;

           break;

         end;

         lpbybuff:=pointer(integer(lpbybuff)+26);

       end;

     end;  //NetSessionEnum

   end

   else

     bRet:=false;

 end  //GetProcAddress

 else

    bRet:=false;

  FreeLibrary(h);

  result:=bRet;

end;