Page 1
Page 2
Page 3
If you want to be a little creative
about how you send information, you can use XML to convey
a structure to your message and allow the receiving application
to have more flexibility to work with your message. A simple
example of this would be:
' Instantiate an XML document
Set xmlDom = CreateObject("Microsoft.XMLDOM")
' Load the XML content
xmlDom.loadXML "<Order><Product>"
& _
cboProduct.Text & "</Product>" &
_
"<Quantity>" & txtQuantity.Text &
_
"</Quantity></Order>"
' Load the message body with actual XML
' rather than XML Document (due to a bug in PPC)
objMsg.Body = xmlDom.xml
By sending a message in this way, you
could automate a remote sales force taking orders in the
field and intermittently transmitting orders back to a main
order system for processing. A receiving application, residing
on a desktop or server, could be notified of a new message,
read the XML and parse out the order information. You could
even return a message stating product availability and confirmation
of the order.
No discussion of a messaging system
would be complete without an explanation of the other half
of the equation - message retrieval. You have two
options when it comes to viewing the contents of a message:
to "peek" at the message and leave it intact or
to read it, and thus remove it from the queue. For the console
application, which is primarily administrative, it was important
to merely peek at the message, since this would allow the
message to remain in the queue for later use.
The process of retrieving a message's
content through a peek or a read is essentially the same.
There is one thing to note though. You can only read messages
out of local, private queues, not outgoing or remote queues.
The following example shows how to peek at the messages
in an already opened queue:
' Peek at first message
Set objMsg = objQueue.PeekCurrent
' Loop as long as we still have a message
Do Until objMsg Is Nothing
MsgBox "Peeked Message: " & objMsg.Label
' Clear message
Set objMsg = Nothing
' Peek at next message -
' wait at most 1/100th of a second
Set objMsg = objQueue.PeekNext ( , , 10)
Loop
That is a quick tour into the realm
of MSMQ, with enough detail to give you the basics of working
through your own MSMQ apps.
There is one word of caution when developing
an MSMQ application. A soft reset will remove all messages
from a queue unless you specifically set the delivery property
of a message to MSMSG_DELIVERY_RECOVERABLE. The default
delivery property is MQMSG_DELIVERY_EXPRESS, which stores
the message in RAM, thereby causing the message to be lost
with a reset. Once the message is sent, it is subject to
being lost in a local queue with a reset, so be aware of
that as well! The recoverable flag guarantees the message
will arrive at its destination, and is stored in file store
until delivery is complete. Here is an example of changing
the delivery property:
' Backup message to file store
objMsg.Delivery = MSMSG_DELIVERY_RECOVERABLE
I want to thank Ken for taking the time
out of his busy schedule to explain to me why my messages
kept disappearing and to show me how to change the default
storage location of the messages to free up system memory
on my Pocket PC! Speaking of that, to move the default MSMQ
directory to another location, for example a CF card, you
need to change the value for "BaseDir" in the
HKEY_LOCAL_MACHINE\Software\Microsoft\MSMQ\SimpleClient
registry key to the new location. Otherwise, the default
directory for the base directory is \Temp\MSMQ. If I am
not mistaken, a reset is also required to reinitialize MSMQ
with the new base directory, since it functions as a driver.
' In module
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const REG_SZ = 1
Public Const gRegBaseDir = _
"\Software\Microsoft\MSMQ\SimpleClient"
' Registry API Declarations
Public Declare Function RegOpenKeyEx Lib _
"Coredll" Alias "RegOpenKeyExW" _
(ByVal hKey As Long, _
ByVal lpSupKey As String, _
ByVal upOptions As Long, _
ByVal samDesired As Long, _
phkResult As Long) As Long
Public Declare Function RegSetValueExString Lib _
"Coredll" Alias "RegSetValueExW" _
(ByVal hKey As Long, _
ByVal lpValueName As String, _
ByVal Reserved As Long, _
ByVal dwType As Long, _
ByVal lpValue As String, _
ByVal cbData As Long) As Long
Public Declare Function RegCloseKey Lib _
"Coredll" (ByVal hKey As Long) As Long
' In form
' Call sub to set register key
SetRegistryKey gRegBaseDir, "BaseDir", _
"\Storage Card\MSMQ"
Private Sub SetRegistryKey(ByVal strKey
As String, _
ByVal strName As String, _
ByVal strValue As String)
' Get handle for the key
lngResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _
strKey, CLng(0), 0, hlngSubKey)
' Set value from key
lngResult = RegSetValueExString(hlngSubKey, _
strName, CLng(0), REG_SZ, strValue, _
Len(strValue) * 2)
' Release handle to key
lngResult = RegCloseKey(hlngSubKey)
End Sub
The procedure for setting the value
of the base directory in the registry is no different than
that for assigning any other string value in the registry.
It references the key and the actual name of the value to
be modified, and then passes in the new value to replace
the current one.
Hopefully, after reading this, you have
seen some areas where your applications would benefit from
the use of MSMQ to manage communication between devices
through its mechanism of messages and queues. Not having
to focus on whether you currently have a connection or not
can be liberating when developing an application that involves
working with intermittently connected devices.
In part two of this article, the focus
will be more on constructing the actual MSMQ Console application
with less attention being given to the mechanics of the
MSMQ control itself. If you are interested in leveraging
some of the more advanced features of the standard eVB controls,
then it should be a worthwhile read.
Previous Page