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

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

在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的开发文档有相当一部分是未公开的,这些未

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

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航