Skip to main content

Past Blast

Featured Products

Windows Mobile Developer Controls
Windows Mobile Developer Controls
Stay in touch using the DEVBUSS RSS feeds.
 

News

Windows Mobile Developer Controls
Windows Mobile Developer Controls

Designing an MSMQ Console Application - Part 1 of 2

Written by Brent Pinkley  [author's bio]  [read 43090 times]
Edited by Derek

Download the code

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