用程序实现自动拨号

在编写网络程序时很可能用到自动拨号。比如,邮件群发软件用自动断线和拨号实现本机IP地址的更换。

要实现自动拨号,分两步:

  1. 从注册表读取本机拨号链接名称;
  2. 自动拨号。

调用API函数从注册表读取本机拨号链接名

以前,我调用API函数从注册表中读取本机拨号链接名称。

在Module中用如下代码:

Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Integer, ByVal   lpSubKey As String, ByRef phkResult As Integer) As Integer
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Integer) As Integer
Private Declare Function RegEnumKey Lib "advapi32.dll" Alias "RegEnumKeyA" (ByVal hKey As Integer, ByVal   dwIndex As Integer, ByVal lpName As String, ByVal cbName As Integer) As Integer
  Const HKEY_CURRENT_USER As Integer = &H80000001
  Const ERROR_NO_MORE_ITEMS As Short = 259
  Const ERROR_SUCCESS As Short = 0

  Dim hKey As Integer
  Dim i As Integer
  Dim astr As String = New String("", 256)
  If RegOpenKey(HKEY_CURRENT_USER, "RemoteAccess\Profile", hKey) = ERROR_SUCCESS Then
    While RegEnumKey(hKey, i, astr, 256) = ERROR_SUCCESS
      MsgBox(astr)  '链接名称
      i += 1
    End While
    RegCloseKey(hKey)
  End If

用RegistryKey 类读取链接名

RegistryKey 类表示 Windows 注册表中的项级节点。此类是注册表封装。

本文主要用到:    RegistryKey.OpenSubKey 方法:用指定的写访问权限检索指定的子项。

以只读方式检索子项。
[Visual Basic] Overloads Public Function OpenSubKey(String) As RegistryKey
RegistryKey.GetSubKeyNames 方法: 检索包含所有子项名称的字符串数组。
Public Function GetSubKeyNames() As String ()
用RegistryKey读取链接名可以说是非常简单:

Dim rk As RegistryKey = _
Registry.CurrentUser.OpenSubKey("RemoteAccess\Profile", True)
' Get the data from a specified item in the key.
Dim s As String() = rk.GetSubKeyNames()

For num As Integer = 0 To s.Length - 1
  MsgBox(s.GetValue(num))           '这就是链接名
Next

用Shell实现自动拨号

读取链接名后,自动拨号就非常简单了。

打开“控制面板”,“网络连接”,连接“属性”,“选项”,去掉“提示名称、密码和证书等(P)”前面的对勾。

shell("rasphone.exe -d" & linksName, AppWinStyle.Hide, True, -1)

启动“命令提示符”,键入 rasphone,回车,就弹出“拨号网络对话框”。

如果键入 rasphone -h,回车,弹出“拨号网络命令行”,列出rasphone的用法,比如,

rasphone -d 表示弹出弹号项目对话框。
rasphone -lx 在拨号快捷方式上执行命令'x'

Shell函数说明:

AppWinStyle.Hide是sheell的参数,表示隐藏窗口并将焦点传到该窗口。
 True表示等待拨号完成。
   -1表示Shell直到程序完成才返回。

也可以这样:

shell("rasdial.exe " & linksName, AppWinStyle.Hide, True, -1)

关于各种命令参数,在OS的“帮助和支持”搜索“命令行”即可查到有关说明。命令行结合Shell函数可实现极多功能,你可试一试。

Shell 函数使用说明:

Public Function Shell ( _ ByVal Pathname As String, _
   Optional ByVal Style As AppWinStyle = AppWinStyle.MinimizedFocus, _
   Optional ByVal Wait As Boolean = False, _
   Optional ByVal Timeout As Integer = -1 _
   ) As Integer

Shell 函数的返回值取决于 Pathname 中指定的程序在 Shell 返回时是否仍在执行。如果将 Wait 设置为 True 并且程序在超时过期前结束, Shell 返回零。如果超时过期或者省略 Wait 或将它设置为 False ,则 Shell 返回程序的进程 ID。进程 ID 是标识正在运行的程序的唯一数字。

如果 Shell 函数无法启动指定的程序,则出现 System.IO.FileNotFoundException 错误。例如,当试图从使用 System.Windows.Forms 的应用程序运行 16 位程序(如 command.com )时,可能会发生这种情况。解决办法是运行将调用所需的 16 位程序的 32 位程序。如果是 command.com ,则可以将运行 cmd.exe 作为另一种选择。

默认情况下, Shell 函数异步运行程序。这意味着用 Shell 函数启动的程序在 Shell 函数后面的语句执行前可能没有结束执行。如果想等待程序结束后再继续,请将 Wait 设置为 True 。

整个路径和文件规范应该始终用引号引起来,如以下示例所示:

ID = Shell ("""C:\Program Files\MyFile.exe"" -a -q", , True, 100000)

字符串内每对相邻的双引号 ( "" ) 被解释为字符串中的一个双引号字符。因此,前面的示例表示 Shell 函数的下列字符串:

"C:\Program Files\MyFile.exe" -a -q

如果路径没有用引号引起来,Windows 就会在 C:\ 目录中查找名为 Program.exe 的文件,而不是在 C:\Program Files 目录中查找 MyFile.exe 文件。

安全说明 如果路径和文件规范没有用引号引起来,那么当文件名或路径节点包含空格时,就会出现安全风险。在上面的示例中,路径节点 \Program Files 包含一个空格。如果规范不在引号中,并且名为 Program.exe 的程序(例如通过非法的破坏)安装在 C:\ 中,Windows 就会执行 Program.exe 程序而不是 MyFile.exe 。

Contributors: FHL