[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

Sending SMS from vb6 app

Stuart McCall

7/29/2012 5:06:00 PM

Hi

Having trouble sending SMS messages from Win7 PC via smartphone from a vb6
app.

Bluetooth connection is working fine. Phone is set up as GSM modem on PC's
COM4:
Using Hyperterminal (copied from a WinXP box) I can send messages just fine
using AT commands, eg:

AT+CMGF=1<enter>
OK
AT+CMGS="+44123456789"<enter>
>
This is the message body<ctrl-z>

The OK and the > prompt are returned from the modem.
So, having established that the connection and the AT commands are working
fine, I attempt to replicate the behaviour from my app. Here's what I
currently have:

Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_EXISTING = 3
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2

Private Declare Sub Sleep Lib "kernel32" _
(ByVal dwMilliseconds As Long)
Private Declare Function WriteFile& Lib "kernel32" _
(ByVal hFile As Long, _
lpBuffer As Any, _
ByVal nNumberOfBytesToWrite&, _
lpNumberOfBytesWritten&, _
ByVal lpOverlapped&)
Private Declare Function CreateFile& Lib "kernel32" _
Alias "CreateFileA" _
(ByVal lpFileName$, _
ByVal dwDesiredAccess&, _
ByVal dwShareMode&, _
ByVal lpSecurityAttributes&, _
ByVal dwCreationDisposition&, _
ByVal dwFlagsAndAttributes&, _
ByVal hTemplateFile&)
Private Declare Function CloseHandle& Lib "kernel32" _
(ByVal hObject&)
Private Declare Function FlushFileBuffers& Lib "kernel32" _
(ByVal hFile&)

Public Sub SendSMS(PhoneNumber$, Message$)
Dim s$

TxModem "AT+CMGF=1" & vbCrLf
TxModem "AT+CMGS=" & _
Chr(34) & PhoneNumber & Chr(34) & vbCrLf
Sleep 100
TxModem Message & Chr(26)
End Sub

Function TxModem(cmd$, Optional CommPort$ = "COM4")
Dim openPort As Long, retVal As Long

openPort = CreateFile(CommPort, GENERIC_WRITE, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
ByVal 0&, OPEN_EXISTING, 0, 0)
If openPort = -1 Then
MsgBox "Unable to open com port " & CommPort
Exit Function
End If

retVal = WriteBytes(openPort, cmd)
If retVal = 0 Then
MsgBox "Unable to write to modem"
Exit Function
End If

CloseHandle openPort
End Function

Private Function WriteBytes(openPort As Long, _
cmd As String) As Long
Dim a(256) As Byte, retBytes As Long, i As Long
'
For i = 0 To Len(cmd) - 1
a(i) = Asc(Mid(cmd, i + 1, 1))
Next
WriteBytes = WriteFile(openPort, a(0), _
Len(cmd), retBytes, 0)
FlushFileBuffers openPort
End Function


Using that code everything seems to be sent to the phone except the EOF
terminator ctrl-z which is ASCII 26.

Does anyone have any idea why the EOF isn't sent? Or is something else
wrong?

As an aside, I've been trying to locate a serial port monitor that will a)
let my app open COM4: while it is being monitored and b) will work on Win7
64bit home premium. No luck so far..

Thanks in advance
Stuart McCall (retired MS Access & VB6 developer, now hobbyist)


18 Answers

Dee Earley

7/30/2012 7:52:00 AM

0

On 29/07/2012 18:05, Stuart McCall wrote:
> As an aside, I've been trying to locate a serial port monitor that will a)
> let my app open COM4: while it is being monitored and b) will work on Win7
> 64bit home premium. No luck so far..

I'd be very surprised if SysInternal's Portmon wouldn't work.
You need to run as admin, and start monitoring the port before you open it.

--
Deanna Earley (dee.earley@icode.co.uk)
i-Catcher Development Team
http://www.icode.co.uk...

iCode Systems

(Replies direct to my email address will be ignored. Please reply to the
group.)

Dee Earley

7/30/2012 8:05:00 AM

0

On 29/07/2012 18:05, Stuart McCall wrote:
> Hi
>
> Having trouble sending SMS messages from Win7 PC via smartphone from a vb6
> app.
>
> Bluetooth connection is working fine. Phone is set up as GSM modem on PC's
> COM4:
> Using Hyperterminal (copied from a WinXP box) I can send messages just fine
> using AT commands, eg:
>
> AT+CMGF=1<enter>
> OK
> AT+CMGS="+44123456789"<enter>
>>
> This is the message body<ctrl-z>
>
> The OK and the > prompt are returned from the modem.
> So, having established that the connection and the AT commands are working
> fine, I attempt to replicate the behaviour from my app. Here's what I
> currently have:
>
<SNIP>
>
> Using that code everything seems to be sent to the phone except the EOF
> terminator ctrl-z which is ASCII 26.
>
> Does anyone have any idea why the EOF isn't sent? Or is something else
> wrong?

I can't see anything immediately wrong. My first thought was the sending
using length or ubound incorrectly, or some form of buffering but it
seems to be correct.

A few points though:

> Function TxModem(cmd$, Optional CommPort$ = "COM4")
> Dim openPort As Long, retVal As Long
>
> openPort = CreateFile(CommPort, GENERIC_WRITE, _
> FILE_SHARE_READ Or FILE_SHARE_WRITE, _
> ByVal 0&, OPEN_EXISTING, 0, 0)

Do you really want to open and close the port for each "chunk" you send?
It may well confuse the modem and/or the flow control.
Open it, write everything (ideally reading the reply) and close when
finished

> TxModem "AT+CMGS=" & _
> Chr(34) & PhoneNumber & Chr(34) & vbCrLf

You can double the quotes in the string literal instead of calling out
to a function:
TxModem "AT+CMGS=""" & PhoneNumber & """" & vbCrLf

> For i = 0 To Len(cmd) - 1
> a(i) = Asc(Mid(cmd, i + 1, 1))
> Next
Probably best to use StrConv(cmd, vbFromUnicode) here (or maybe even a
UTF-8 conversion (I think SMSs use UTF-8))

> As an aside, I've been trying to locate a serial port monitor that will a)
> let my app open COM4: while it is being monitored and b) will work on Win7
> 64bit home premium. No luck so far..

I'd be very surprised if SysInternal's Portmon wouldn't work.
You need to run as admin, and start monitoring the port before you open it.

--
Deanna Earley (dee.earley@icode.co.uk)
i-Catcher Development Team
http://www.icode.co.uk...

iCode Systems

(Replies direct to my email address will be ignored. Please reply to the
group.)

Stuart McCall

7/30/2012 11:34:00 AM

0

Thanks for your reply Deanna. Responses inline:

"Deanna Earley" <dee.earley@icode.co.uk> wrote in message
news:jv5f7f$pbf$2@speranza.aioe.org...
> On 29/07/2012 18:05, Stuart McCall wrote:
>> Hi
>>
>> Having trouble sending SMS messages from Win7 PC via smartphone from a
>> vb6
>> app.
>>
>> Bluetooth connection is working fine. Phone is set up as GSM modem on
>> PC's
>> COM4:
>> Using Hyperterminal (copied from a WinXP box) I can send messages just
>> fine
>> using AT commands, eg:
>>
>> AT+CMGF=1<enter>
>> OK
>> AT+CMGS="+44123456789"<enter>
>>>
>> This is the message body<ctrl-z>
>>
>> The OK and the > prompt are returned from the modem.
>> So, having established that the connection and the AT commands are
>> working
>> fine, I attempt to replicate the behaviour from my app. Here's what I
>> currently have:
>>
> <SNIP>
>>
>> Using that code everything seems to be sent to the phone except the EOF
>> terminator ctrl-z which is ASCII 26.
>>
>> Does anyone have any idea why the EOF isn't sent? Or is something else
>> wrong?
>
> I can't see anything immediately wrong. My first thought was the sending
> using length or ubound incorrectly, or some form of buffering but it seems
> to be correct.

My frst thought too, having been bitten by such things in the past. But it's
been checked and double-checked so many times I've lost count :-)

>
> A few points though:
>
>> Function TxModem(cmd$, Optional CommPort$ = "COM4")
>> Dim openPort As Long, retVal As Long
>>
>> openPort = CreateFile(CommPort, GENERIC_WRITE, _
>> FILE_SHARE_READ Or FILE_SHARE_WRITE, _
>> ByVal 0&, OPEN_EXISTING, 0, 0)
>
> Do you really want to open and close the port for each "chunk" you send?
> It may well confuse the modem and/or the flow control.
> Open it, write everything (ideally reading the reply) and close when
> finished

You're right. That's how I originally had it. The code I posted has
undergone tons of alterations, that being one of them. It'll be corrected
soon.
Reading the responbse is something I don't know how to do (yet :) It'll
probably involve reading in a loop, but for how long or until what
condition?

>
>> TxModem "AT+CMGS=" & _
>> Chr(34) & PhoneNumber & Chr(34) & vbCrLf
>
> You can double the quotes in the string literal instead of calling out to
> a function:
> TxModem "AT+CMGS=""" & PhoneNumber & """" & vbCrLf

Yes I supose so, but there's no performance issue in this instance, and I
find it more readable the other way. Personal preference only.

>
>> For i = 0 To Len(cmd) - 1
>> a(i) = Asc(Mid(cmd, i + 1, 1))
>> Next
> Probably best to use StrConv(cmd, vbFromUnicode) here (or maybe even a
> UTF-8 conversion (I think SMSs use UTF-8))

Now that's worth a try. Hadn't thought of that. I was about to test it just
now but my phone's battery was flat. I'll try it later and let you know the
outcome (the phone's bluetooth doesn't work while it's charging,
apparently).

g monitored and b) will work on Win7
>> 64bit home premium. No luck so far..
>
> I'd be very surprised if SysInternal's Portmon wouldn't work.

Well prepare to be surprised. Whether run as admin or otherwise all I get
is a msgbox that says 'Error 2'. The portmon help file (which can't be read
on Win7) has no list of error codes.

I've tried a few other freeware offerings, only one of which will run.
That's called FoxTerm. It does monitor the port correctly (tested using
Hyperterminal) but when I attempt to open the port in code I receive a
'permission denied. Port already in use' error.

/
>
> iCode Systems
>
> (Replies direct to my email address will be ignored. Please reply to the
> group.)


Dee Earley

7/30/2012 12:00:00 PM

0

On 30/07/2012 12:34, Stuart McCall wrote:
> "Deanna Earley" <dee.earley@icode.co.uk> wrote in message
> news:jv5f7f$pbf$2@speranza.aioe.org...
> Reading the responbse is something I don't know how to do (yet :) It'll
> probably involve reading in a loop, but for how long or until what
> condition?

Until you get a valid "I've received that and it's OK/incorrect"
response from the modem.
It's a long time since I dealt with the AT command set, but there is
defined reply standard.

>> You can double the quotes in the string literal instead of calling out to
>> a function:
>> TxModem "AT+CMGS=""" & PhoneNumber & """" & vbCrLf
>
> Yes I supose so, but there's no performance issue in this instance, and I
> find it more readable the other way. Personal preference only.

It does have a performance impact, but probably not something you'll notice.

"""" is a literal, and hard coded.
Chr(34) involves putting the ASCII code on the stack, calling a
function, getting the return value, then appending the string results.

As the literal uses no CPU time, the latter takes infinitely times
longer to run :p

--
Deanna Earley (dee.earley@icode.co.uk)
i-Catcher Development Team
http://www.icode.co.uk...

iCode Systems

(Replies direct to my email address will be ignored. Please reply to the
group.)

Stuart McCall

7/31/2012 11:51:00 PM

0

"Deanna Earley" <dee.earley@icode.co.uk> wrote in message
news:jv5sv0$ss9$1@speranza.aioe.org...
> On 30/07/2012 12:34, Stuart McCall wrote:
>> "Deanna Earley" <dee.earley@icode.co.uk> wrote in message
>> news:jv5f7f$pbf$2@speranza.aioe.org...
>> Reading the responbse is something I don't know how to do (yet :) It'll
>> probably involve reading in a loop, but for how long or until what
>> condition?
>
> Until you get a valid "I've received that and it's OK/incorrect" response
> from the modem.
> It's a long time since I dealt with the AT command set, but there is
> defined reply standard.
>
>>> You can double the quotes in the string literal instead of calling out
>>> to
>>> a function:
>>> TxModem "AT+CMGS=""" & PhoneNumber & """" & vbCrLf
>>
>> Yes I supose so, but there's no performance issue in this instance, and I
>> find it more readable the other way. Personal preference only.
>
> It does have a performance impact, but probably not something you'll
> notice.
>
> """" is a literal, and hard coded.
> Chr(34) involves putting the ASCII code on the stack, calling a function,
> getting the return value, then appending the string results.
>
> As the literal uses no CPU time, the latter takes infinitely times longer
> to run :p
>
> --
> Deanna Earley (dee.earley@icode.co.uk)
> i-Catcher Development Team
> http://www.icode.co.uk...
>
> iCode Systems
>
> (Replies direct to my email address will be ignored. Please reply to the
> group.)

Thanks for the 'quotes 101'

FWIW I tried your suggestion of converting to UTF-8. No go I'm afraid. I
also modified the code to leave the port open till I finished sending, which
also didn't help.

I think I may try using mscomm, although I was attempting to avoid having an
external reference. But seeing as the app will only be used by me it could
probably be worth a try.

Unless anyone else can suggest something?


Stuart McCall

8/1/2012 3:01:00 AM

0

As a quick follow-up, I tried using mscomm and it worked first time. Here's
what I have for anyone interested. In my form's load event:

With Me.MSComm1
.CommPort = 4
.Settings = "9600,N,8,1"
.Handshaking = comRTS
.RTSEnable = True
.DTREnable = True
.RThreshold = 1
.SThreshold = 1
.InputMode = comInputModeText
.InputLen = 0
.PortOpen = True
End With

and in a command button's click event:

Const qt = """"
'
a = Split(EndStats(Me), "|")
s$ = a(0) & " Minutes of Music Left." & vbCrLf
s = s & "Finishing At About: " & a(1)
Me.MSComm1.Output = "AT" & vbCrLf
Sleep 500
Me.MSComm1.Output = "AT+CMGF=1" & vbCrLf
Sleep 500
Me.MSComm1.Output = "AT+CMGS=" & qt & "+441234567890" & qt & vbCrLf
Sleep 1000
Me.MSComm1.Output = s & Chr(26)
Sleep 2000
MsgBox "Message Sent"


Sorry for any line-wrap.


Stuart McCall

8/1/2012 3:09:00 AM

0

PS: The lines starting with:

a =
s$ =
s = s &

are part of my app's logic and may be ignored or replaced with:

This is the message body


ObiWan

8/1/2012 11:17:00 AM

0

> As a quick follow-up, I tried using mscomm and it worked first time.
> Here's what I have for anyone interested. In my form's load event:
>
> With Me.MSComm1
> .CommPort = 4
> .Settings = "9600,N,8,1"
> .Handshaking = comRTS
> .RTSEnable = True
> .DTREnable = True
> .RThreshold = 1
> .SThreshold = 1
> .InputMode = comInputModeText
> .InputLen = 0
> .PortOpen = True
> End With

Heh... and here goes the missing part in previous code, when you called
the createfile you opened the device but you didn't specify the speed,
parity and the other settings and that's probably why you were unable
to talk to the device; if you want to avoid the MsComm and only use
APIs you'll need to have a look at this example

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363201%28v=vs....

which shows how to retrieve/set the serial port settings, just
translate the code to VB and you'll be on your way... or I hope so





ObiWan

8/1/2012 12:38:00 PM

0

> were unable to talk to the device; if you want to avoid the MsComm
> and only use APIs you'll need to have a look at this example
>
> http://msdn.microsoft.com/en-us/library/windows/desktop/aa363201%28v=vs....
>
> which shows how to retrieve/set the serial port settings, just
> translate the code to VB and you'll be on your way... or I hope so

And also http://msdn.microsoft.com/en-us/library/aa4...

notice that it would be a good idea wrapping the whole code inside a
class module so that all the API calls and details will sit inside the
class and your main code will just have to create an instance of such a
class and then use the exposed properties/methods, also notice that in
many cases, when sending commands to devices they will return you some
response (e.g. a status code or something like that) so you may want to
check if the serial receive buffer contains something and eventually
read it "until EOF" to ensure the command you sent was correctly
processed by the device

As for the class, at a bare minimum, you may want to implement...

Public enum enBaudRate

Public enum enParity

Public enum enHandShake

Public Property Get/Let CommPort(nPort As Integer) As Integer

Public Property Get/Let Speed(nBaud As enBaudRate) As enBaudRate

Public Property Get/Let Parity(nParity As enParity) As enParity

Public Property Get/Let DataBits(nBits As Integer) As Integer

Public Property Get/Let StopBits(nBits As Integer) As Integer

Public Property Get/Let HShake(nHShake As enHandShake) As enHandShake

Public Property Get IsOpen() As Boolean

Public Property Get ErrNum() As Long

Public Property Get ErrMsg() As String

Public Function Open() As Boolean

Public Function Write(sBuff As String) As Boolean

Public Function Read(sBuff As String) As Boolean

Public Function Close() As Boolean

HTH


ObiWan

8/1/2012 12:40:00 PM

0

> Me.MSComm1.Output = "AT" & vbCrLf
> Sleep 500

forgot... those "sleep" may be avoided, just ensure to add code to the
"receive" event, the remote end will most probably send back a
response, so, instead of blindly sending out commands and waiting you'd
better check for the reply (and raise an error if needed !)