方法1c:使用ras
ras 是微软的远程访问服务(remote access service)api集合。其中的 api函数rasdial可完成拨号任务。但由于该函数在使用上略显复杂而不太常用,故示例程序中未采纳。
自动拨号方法小结:rnaui方法使用起来最简单,又由于它不一定非要使用默认连接,因此也最灵活。但这种灵活恰恰又给它带来了弱点,即如果不提供连接名,该方法不会自动调用默认连接。此外,这种方法还有两个最大的缺点:一是仅拨号一次,若出现占线或没有响应等情况时不会自动重试;二是调用程序不容易得到拨号是否成功的返回值。相比之下,wininet方法虽仅能拨打默认连接(无默认连接时,使用第一个连接),但它可多次试拨,并且internetautodial函数等待拨号成功或所有试拨结束以便给调用程序返回拨号是否成功的值,因此,在“自动上网机器人”的环境中wininet方法是最适宜的。
方法2a:wininet方法
若internetgetconnectedstate函数返回true,则为在线状态。该方法最大的缺点是:若当前连接不是用wininet方法建立的,则返回值可能不准确。
方法2b:查找窗口法
拨号连接成功后,下图所示的窗口一定存在(不管它是最小化在任务栏的最右端,或是开启为下图所示的状态):
![]() |
用findwindow api函数找到该窗口即意味着当前在线。此外,查找窗口法的另一个用处是查找“重新连接”窗口:当中途掉线时,操作系统往往会询问你是否重新连接,找到该窗口并发出模拟“回车”按键即可实现再拨号。
查找窗口法的缺点是:由于找窗口时需要提供窗口标题,因此即使使用的是默认连接也必须事先知道默认连接名。
方法2c:ras 方法
先用rasenumconnections函数返回整个ras集合,再用rasgetconnectstatus函数判断第一个 ras连接的状态。ras方法的最大优点是:不管当前连接是否是用wininet建立的,ras 方法均可对在线状态做出正确判断。
方法2d:注册表法
在线时,注册表的“\hkey_local_machine\system\currentcontrolset\services\remoteaccess”处有键值“remote connection”,且其值不为零;不在线时,该处无“remote connection”键值(当本次系统启动后从未拨号成功时),或者其值为零(表明曾拨号成功,但现在已断掉)。
检查在线状况之方法小结:由于wininet方法的局限性,一般我们应避免使用之;查找窗口法是可靠的,只是要知道连接名;因此我们推荐使用ras 方法和注册表法。
方法3a:wininet法
使用internetautodialhangup函数。同样地,若当前连接不是用wininet方法建立的,则返回值可能不准确(即不能成功挂断)。
方法3b:窗口查找法
找到图九所示的窗口,然后用showwindow api函数使之成为当前窗口,最后发出模拟<alt>+c的按键操作(从图九中可以看出,<alt>+c是“断开连接”按键的快捷方式)。
方法3c:ras 法
用rashangup函数执行挂断。不管用何种方法建立的连接,ras 法均能可靠地完成任务。
自动挂断方法小结:相比之下,窗口查找法和ras 法是可以信赖的。
综上所述,对于“自动拨号”、“检查在线状况”、以及“自动挂断”的各种方法,我们推荐“1a-2c-3c”组合。当然各方法可综合使用(如加入2d、3b等),以确保万无一失。在具体编程时还应注意:拨号后判断结果,如不成功应重新拨号;任务进行过程中定时检查在线状态,出现掉线后应及时处理;最后的挂断操作后应再查在线状态,以确保挂断成功。
下面是实例程序的完整代码。源代码中的全局定义已按照wininet、ras、注册表等进行分类,各具体方法也均按序排列,以便于大家挑选使用。该程序的执行情况在本部分的开始处已给出(图六)。
| ' 程序三:自动拨号、自动挂断以及自动处理中途掉线 ' option explicit ' 有关 wininet 的全局定义 private const internet_autodial_force_unattended = 2 private const internet_connection_modem = 1 private declare function internetautodial lib "wininet.dll" _ (byval dwflags as long, byval dwreserved as long) as long private declare function internetautodialhangup lib _ "wininet.dll" (byval dwreserved as long) as long private declare function internetgetconnectedstate lib _ "wininet.dll" (byref lpdwflags as long, byval _ dwreserved as long) as long ' 有关“窗口查找”的全局定义 private declare function findwindow lib "user32" _ alias "findwindowa" (byval lpclassname as string, _ byval lpwindowname as string) as long private declare function showwindow lib "user32" _ (byval hwnd as long, byval ncmdshow as long) as long private const sw_show = 5 ' 有关 ras 的全局定义 private const rascs_done = &h2000& private const ras_maxentryname = 256 private const ras_maxdevicetype = 16 private const ras_maxdevicename = 128 private type rasconn dwsize as long hrasconn as long szentryname(ras_maxentryname) as byte szdevicetype(ras_maxdevicetype) as byte szdevicename(ras_maxdevicename) as byte end type private type rasconnstatus dwsize as long rasconnstate as long dwerror as long szdevicetype(ras_maxdevicetype) as byte szdevicename(ras_maxdevicename) as byte end type private ras_buf(255) as rasconn private ras_status as rasconnstatus private lpcb as long private lpcconnections as long private declare function rasenumconnections lib _ "rasapi32.dll" alias "rasenumconnectionsa" (lprasconn _ as any, lpcb as long, lpcconnections as long) as long private declare function rasgetconnectstatus lib _ "rasapi32.dll" alias "rasgetconnectstatusa" (byval _ hrasconn as long, lprasconnstatus as any) as long private declare function rashangup lib "rasapi32.dll" _ alias "rashangupa" (byval hrasconn as long) as long ' 有关“注册表”的全局定义 private const hkey_local_machine = &h80000002 private declare function regopenkey lib "advapi32.dll" alias _ "regopenkeya" (byval hkey as long, byval lpsubkey as _ string, phkresult as long) as long private declare function regqueryvalueex lib "advapi32.dll" _ alias "regqueryvalueexa" (byval hkey as long, byval _ lpvaluename as string, byval lpreserved as long, lptype _ as long, lpdata as any, lpcbdata as long) as long private declare function regclosekey lib "advapi32.dll" _ (byval hkey as long) as long dim ret as long '自动拨号 private sub wininet拨号测试_click() if internetautodial(internet_autodial_force_unattended, 0) _ then msgbox "已连接(wininet法)" end sub private sub rnaui拨号测试_click() ret = shell("rundll32.exe rnaui.dll,rnadial " + text1, 1): doevents sendkeys "{enter}", true: doevents end sub '检查是否断线 private sub wininet方法_click() ' wininet法检查是否断线 if internetgetconnectedstate(internet_connection_modem, 0) then msgbox "在线." else msgbox "当前未连接。" end if end sub private sub 查找窗口法_click() ' 查找窗口法检查是否断线 ret = findwindow("#32770", "重新连接") if ret <> 0 then call showwindow(ret, sw_show) sendkeys "{enter}", true: exit sub end if ret = findwindow("#32770", "连接到 the95963") if ret <> 0 then msgbox "在线." else msgbox "当前未连接。" end if end sub private sub ras方法_click() ' ras方法检查是否断线 ras_buf(0).dwsize = len(ras_buf(0)) + 1 lpcb = 256 * ras_buf(0).dwsize ret = rasenumconnections(ras_buf(0), lpcb, lpcconnections) if ret then msgbox "出错!": exit sub end if ras_status.dwsize = len(ras_status) + 2 ret = rasgetconnectstatus(ras_buf(0).hrasconn, ras_status) if ret = 0 and ras_status.rasconnstate = rascs_done then msgbox "在线." else msgbox "当前未连接。" end if end sub private sub 注册表法_click() ' 注册表法检查是否断线 dim subkey as string, valuename as string dim data as long, result as long subkey = "system\currentcontrolset\services\remoteaccess" ret = regopenkey(hkey_local_machine, subkey, result) if ret = 0& then valuename = "remote connection" ret = regqueryvalueex(result, valuename, 0&, 0&, byval data, 0&) ret = regqueryvalueex(result, valuename, 0&, 0&, data, len(data)) if ret = 0& and data <> 0 then msgbox "在线!" else msgbox "当前未连接。" end if regclosekey (result) end if end sub '自动挂断 private sub wininet法_click() ' wininet法自动挂断 if internetautodialhangup(0) then msgbox "已挂断(wininet法)" end sub private sub 窗口查找法_click() ' 窗口查找法自动挂断 ret = findwindow("#32770", "连接到 the95963") if ret <> 0 then call showwindow(ret, sw_show) sendkeys "%c", true msgbox "已挂断(窗口查找法)" end if end sub private sub ras法_click() ' ras法自动挂断 ras_buf(0).dwsize = len(ras_buf(0)) + 1 lpcb = 256 * ras_buf(0).dwsize ret = rasenumconnections(ras_buf(0), lpcb, lpcconnections) if ret then msgbox "出错!": exit sub end if ras_status.dwsize = len(ras_status) + 2 ret = rasgetconnectstatus(ras_buf(0).hrasconn, ras_status) if ret = 0 and ras_status.rasconnstate = rascs_done then if rashangup(ras_buf(0).hrasconn) = 0 then _ msgbox "已挂断(ras法)" end if end sub |