2

Currently, there are around 20-30 computers into which I dial on a regular basis. I am currently using HyperTerminal on Windows XP SP3 to do this. Once my computer connects to the other computer, I get a string printout of some information which I manually eyeball and type into Excel.

While it works well for manual connections, it's a tedious process that I feel should be automated. I'm doing it once a week, now, because it's so laborious (usually 30-40 minutes per), but ideally I'd like to have it run as a scheduled task every day. However, HyperTerminal doesn't seem to offer any scripting capabilities. Furthermore, I tried using the session logging feature and it doesn't seem to work reliably that well.

Is there some way, perhaps using a batch or VBS or PowerShell script, that I could sequentially dial a series of computers, and then automatically log the terminal output to a text file, timestamped?

The added caveat is I also need to be able to handle exceptions, e.g. if the computer is busy. HyperTerminal has a "Redial on Busy" feature, and sometimes I use that or dial the rest of the computers and then come back to that one. I need to build that into my script, also.

Considering that war dialing is possible, although it doesn't log the output, only the absence or presence of a carrier tone, I feel like this is achievable. How might I go about implementing this?

I need a Batch or VBS solution, if possible. I'm not sure how good PowerShell support is on Windows XP, and for various reasons, I'd prefer not to install any additional tools (e.g. Python, etc.) onto the machine.

Clarification: I have a friend who at one point made a script that could dial out using Hayes commands onto the line. That's the easy part; the hard part is being able to detect the printout from the remote computer and log that to a text file.

The paid version of HyperTerminal offers facilities to script things along these lines, but I would like to do this for free by using a custom script, with the ability to handle busy numbers as well.

Thanks!

PowerShell

Here's what I get when running the PowerShell script: enter image description here

Here is the script I tried:

# Create your instance of the SerialPort Class
$serialPort = new-Object System.IO.Ports.SerialPort
# Set various COM-port settings
$serialPort.PortName = "COM3"
$serialPort.BaudRate = 1200
$serialPort.WriteTimeout = 500
$serialPort.ReadTimeout = 23000
$serialPort.DtrEnable = "true"
# or in one command
# $serialPort= new-Object System.IO.Ports.SerialPort COM#,Baudrate,None,8,one
# Open the connection
$serialPort.Open()
# write to it
$serialPort.WriteLine( "at+csq" + "`r" )
$serialPort.WriteLine( "atdt1NPANXXXXXX" + "`r" )
# wait
start-sleep -m 50
# read line
$line = $serialPort.ReadLine()
Write-Host $line
# write to it
$serialPort.Close()

Closest Solution So Far:

Closest I've been able to get is using AHK, which is quite finicky, but works enough of the time to be useful. My plan is to hook it up a batch script and pass in each number and iterate through until I've successfully gotten a printout from each computer.

InterLinked
  • 2,635

4 Answers4

3

A tool that could help with your problem is the AT Command Tester Desktop App, a commercial product ($9.95) with 7-day free trial.

This product can execute a script of AT commands under its "Script Mode" tab, where it can save and load the script from the local computer.

It also has a command line mode where it can be called by:

atc –port portname –script filename

The tool can also collect and save modem logs. I have not tried it, as I don't have a modem or know any number to call, but if the logs are saved as text files it should be a simple matter to write a little text-search script for errors/success.

enter image description here


If you would prefer writing your own, a simple PowerShell script may do it, using the System.IO.Ports.SerialPort class.

Here is an example (untested and very theoretical) :

# Create your instance of the SerialPort Class
$serialPort = new-Object System.IO.Ports.SerialPort
# Set various COM-port settings
$serialPort.PortName = "COM1"
$serialPort.BaudRate = 19200
$serialPort.WriteTimeout = 500
$serialPort.ReadTimeout = 3000
$serialPort.DtrEnable = "true"
# or in one command
# $serialPort= new-Object System.IO.Ports.SerialPort COM#,Baudrate,None,8,one
# Open the connection
$serialPort.Open()
# write to it
$serialPort.WriteLine( "at+csq" + "`r" )
# wait
start-sleep -m 50
# read line
$line = $serialPort.ReadLine()
Write-Host $line
# write to it
$serialPort.Close()

Note that the end of line character as used by the modem needs attention.

Here is my session on an XP VM where I installed .Net Framework 2.0 and KB968930. It almost worked, except that there is nothing connected to COM1, so it hanged on the ReadLine() call until ended by a timeout.

Please note that there was a copy-paste error in my script, now corrected. The line that didn't work was:

$line = $port.ReadLine()

It should have been:

$line = $serialPort.ReadLine()

enter image description here

harrymc
  • 498,455
2

The most basic method of controlling a modem is by sending commands through a serial port. Nearly all dial-up modems support Hayes AT commands, such as ATD or ATH (usually in hardware for serial modems, sometimes emulated by the driver for USB/PCI modems).

Examples:

  • Linux/OpenBSD/FreeBSD: All programs and libraries eventually use the /dev/ttyS* special files to access serial ports. (Note: On Linux, USB-serial adapters are named ttyUSB or ttyACM.)
    In most cases your program can just open the path as if it were a regular file, then write/flush a command and read the response.

  • Windows: All programs eventually use the \\.\COM1: special files to access serial ports. The first four can be opened simply as COM1: (the shortcut is a MS-DOS relic).

  • PowerShell: There is a DevBlog on this topic.

  • Python: Use pySerial.

The other method, on Windows, might be to use the Telephony API. However, I can't find whether it supports data (terminal) calls, or only voice calls.

grawity
  • 501,077
1

As a sidenote: here are just two utilities I use to control my modems. I send and receive lots of SMS, the tools are made for this. They support multiple modems, and AT commands are used to initialize modems. Whereas all functions are somehow laid out to work with SMS, it can be highly customized with init scripts and more. I haven't tested a complete cycle like dial in another modem and receive somehow data, but maybe it is worthwhile to have a look into them:

http://smstools3.kekekasvi.com/index.php https://wammu.eu/smsd/

1

AutoHotkey.com can be helpful.

I believe that a key trick to making it work reliably will be to use the right approach. Simply dumping keystrokes into Microsoft Windows so that Windows give it to the foreground application will not be the most stable method. Here is a bit of code that I used to interact with PuTTY. It worked well enough that I could start the script, which would launch PuTTY, and yet the program could then interact with the correct instance of PuTTY even if PuTTY was in the background.

(You will likely want to significantly adapt this example code.)

sPuTTYloc:="C:\Users\\me\PuTTY\PuTTY.exe"
sSiteName:="NameOfSite"
Run, "%sPuTTYloc%" -load "%sSiteName%",,UseErrorLevel,sPuTTYPID

    if %sPuTTYPID%
    {
        WinWait, ahk_pid %sPuTTYPID%
        sleep ,5000
        IfWinExist,ahk_pid %sPuTTYPID%
        {
            ControlSend,,{Enter},ahk_pid %sPuTTYPID%
; other stuff
        else
        {
MsgBox "PuTTY Window closed, spot #1"
            return ; Apparently the PuTTY window closed
        }
        Sleep 1500
        IfWinExist,ahk_pid %sPuTTYPID%
        {
            ; do other stuff
        }
        else
        {
MsgBox "PuTTY Window closed, spot #2"
            return ; Apparently the PuTTY window closed
        }
        Sleep 1500
        return
    }
return

There isn't necessarily a compelling reason why I still have things broken things up into pieces, calling "IfWinExist" multiple times. When I was creating and initially debugging the script, I found it useful for debugging (or at least feeling like I had a better idea of what was going on) if the remote end terminated the connection (which would cause my PuTTY window to close).

The main thing is that by using ControlSend to give the keystrokes to the program using the PID which was created by my Run command, if something bad happened, the script didn't continue to try to send keystrokes to Windows and end up having the keystrokes go into the wrong program.

TOOGAM
  • 16,486