|n the last few months I've had the opportunity to talk with quite a few people about Microsoft® Message Queuing (MSMQ) on handheld devices running Windows® CE. The initial reaction of nearly every person I've spoken with is surprise that MSMQ is supported on small, handheld devices. It seems that in the minds of most people, MSMQ is lumped into the category of large and complex technologies.|
This is purely a case of guilt by association. Message queuing has proven to be extremely useful on the server side of large, heterogeneous networks running complex, high-volume applications, and vendors are eager to point this out to highlight the industrial strength of their messaging products. With IBM citing MQSeries coming to the rescue of financial call centers processing millions of transactions per month, and Microsoft describing the MSMQ-enabling of the largest yachting event in the world, it's no wonder that many people see messaging technologies like MSMQ as applicable only at the large scale of big iron.
Though messaging technologies are nicely suited to support such complex and large-scale implementations (guaranteed delivery of critical data, heterogeneous platform support, and so on), the fact of the matter is that in their simplest form they are nothing more than a mechanism for applications to communicate with each other regardless of their ability to connect directly to one another. This means that they are applicable in any environment where multiple applications must coordinate with each other over unreliable connections. If this reminds you of the current wireless computing environment, then you're on the right train of thought.
Handheld and Pocket PC devices are increasingly being positioned as mobile distributed computing nodes that connect to the enterprise through wireless networks. Because of the unreliability of today's wireless connections, these devices often require store-and-forward messaging capabilities to allow their applications to continue to function regardless of the state of the wireless connection. Products like MSMQ are well-suited to fill this important role. For example, using MSMQ for Windows CE here at Stellcom Inc., we recently developed a sales force automation application that demonstrates how sales representatives can submit orders, receive acknowledgment of receipt, and receive shipment confirmation all without regard to the current state of their wireless connection.
In this article, I'll talk more about the applicability of MSMQ on Windows CE, and I'll also give you some pointers on how to install and configure it. I'll also discuss programming against the MSMQ for Windows CE API using eMbedded C++ for Windows CE and give you some code samples. Before I go any further though, I'll review a few basics of the technology.
A Brief MSMQ Refresher As mentioned earlier, at its most basic MSMQ is really nothing more than a way for applications to communicate with each other without having to establish a direct communication link between them. Think of it as inter-application communication without the need for a live connection between applications. Of course MSMQ has other characteristics, such as guaranteed message delivery, routing, security, and message prioritization, but these characteristics are all in support of this core capability of disconnected inter-application communication.
MSMQ accomplishes this magic by accepting a sending application's messages and placing them in a message queue that is accessible by the receiving application. A receiving application can connect to the queue at any time to retrieve messages that have been left for it, and in response it can send messages back through the same queuing mechanism. Figure 1 illustrates this process.
Figure 1 Message Queue
If the queues involved are inaccessible (because of a network disconnection, for example), MSMQ will retry. For example, if the sending application is directing its messages to a remote queue (a queue not on the local machine) and that queue cannot be reached, MSMQ stores the message in a local outbound queue and attempts to resend at the appropriate time. The effect of this is guaranteed delivery: all the user has to do is click the Submit button and he can rest assured that MSMQ will deliver the message.
In addition to the specific data sent by the sending application, MSMQ messages include several types of metadata in the form of message properties. To provide additional information about the message to the receiving application, MSMQ tags messages with property values such as the time of send, the time of arrival, the identification of the sender, and the machine identifier of the computer from which the message was sent.
Additional metadata can be explicitly set by the sending application, including a message label, processing priority indicator, and specification of a queue to which the receiving application should send any responses. Finally, the sending application can monitor messaging by setting message properties indicating to MSMQ that tracking information such as receipt acknowledgments and routing traces should be returned.
Queues come in two flavors: system queues and application queues. System queues are established and used by MSMQ for administrative activities such as routing and dead letter collection. Application queues are created and used by applications for the purpose of communicating with one another.
Application queues fall into two categories: public and private. The distinction primarily has to do with visibility of the queues. Public queues are registered in Active Directory™ so they can be located by any MSMQ application that can search an Active Directory. Private queues are registered only on the local computer, so they are not explicitly visible throughout the network.
Private queues can be accessed only if an MSMQ application has specific foreknowledge that the queue exists, or if a sending application provides the receiving application with the private queue name in a message property (as a queue to which responses should be sent, for example). Understanding private queues is important in MSMQ for Windows CE, since it only supports creation of local private queues. In addition to their definition as public or private, queues also have properties such as maximum size, queue label, and creation time.
On top of all this, MSMQ integrates with other Microsoft enterprise technologies. For example, MSMQ can function in concert with Microsoft Transaction Services (MTS). By integrating with MTS, the Microsoft Distributed Transaction Coordinator (MS DTC) can coordinate MSMQ operations as part of an MTS transaction, such as preventing the sending of an MSMQ message if a database operation within the same MTS transaction fails.
Now that you've been refreshed with the basics of MSMQ, I do need to tell you that MSMQ for Windows CE is a subset of the full MSMQ capability. Let's take a look at what is and what isn't supported in the Windows CE implementation of MSMQ.
MSMQ Support in Windows CE Windows CE is designed as an embedded operating system for small footprint and mobile 32-bit devices. Windows CE powers everything from consumer electronic devices to specialized industrial controllers. These types of devices are often resource-sensitive, hence the highly modular and minimal resource profile of Windows CE. It follows that applications developed for Windows CE-based devices must focus on efficiency and a small memory footprint.
In keeping with these design constraints, MSMQ for Windows CE focuses on providing the core features of MSMQ desktop, but with an emphasis on optimizing space requirements (with a footprint of only 100-150KB) and adding a few features helpful to mobile devices (such as a wait period for connecting to an MSMQ base directory that may be stored on installable file systems, such as flash cards, that initialize late in the boot cycle).
Figure 2 highlights a few of the features you may be familiar with in desktop MSMQ that are not supported in MSMQ for Windows CE. These unsupported features are worth a quick review. As you can see, reading messages from queues that exist on a remote machine is not supported, which is nothing new to those of you who have worked with desktop MSMQ in ASP since you've lived without it for a long time.
As for security, key-encrypted messages are not supported, and queues are not securable objects in the Windows CE version of MSMQ as they are in desktop MSMQ. The inability to secure queues is not as severe a restriction as it might seem, since all queues created using MSMQ are local private queues. MQMail, which refers to MSMQ interaction with e-mail-based applications through the use of MIME-format messages, is also unsupported.
Note that a handheld device (with Windows CE) running MSMQ cannot function as a dependent client. Instead, it functions as an independent client, which means that it does not require access to a message queuing server or domain controller as a dependent client would. This is a reasonable assumption for devices that may often want to work in a disconnected mode. The impact of this is that with MSMQ for Windows CE you cannot search a directory service to locate a public queue, so you need to know the computer on which the queue resides. This also means that only DIRECT naming formats can be used. I'll talk about a workaround to this later on.
Note also that MSMQ cannot participate in coordinated transactions via MS DTC. However, single message transactions are supported, which is MSMQ terminology for guaranteed once-only, in-order delivery on the sending (not receiving) of messages. Finally, as mentioned previously, MSMQ for Windows CE only supports the creation of local private queues, which is an attractive feature in devices that are often offline because private queues are addressed with much less overhead and can be created, deleted, and manipulated without requiring connectivity to a remote directory service.
Despite the lack of support for these features, MSMQ for Windows CE supports many features that desktop MSMQ developers are used to working with. I've taken Figure 3 directly from the documentation to show you the MSMQ functions that are available on Windows CE and how they may differ from their desktop implementation. It's also worth noting that in support of the wireless nature of many MSMQ devices, MSMQ for Windows CE adds some new twists, such as NIC tracking. This allows a user to indicate that MSMQ should retry delivery of undelivered messages as soon as (or after a specified wait time) MSMQ senses a network reconnect, such as when a wireless connection is regained.
Putting all this together, the picture of MSMQ for Windows CE is exactly what you would expect for use on an often mobile, sometimes disconnected device: a space-and-resource-optimized implementation of a store-and-forward mechanism designed to support the sending and receiving of messages in an often isolated environment. By now you are probably wondering how to get all of this up and running on your Windows CE-based device, so let's take a look at installation and configuration.
Installing and Configuring MSMQ on Windows CE Installing and configuring MSMQ on Windows CE requires just a few easy steps:
In the next four sections, I'll walk you through each of these steps.
- Copying the MSMQ program files to the device running Windows CE
- Installing MSMQ
- Configuring registry entries
- Starting the MSMQ device driver. Note that MSMQ for Windows CE is implemented as a device driver that loads when MSMQ is started
- Configuring name resolution
Load the MSMQ Program Files On some platforms you may find that the MSMQ runtimes already exist in ROM on your device. Take a look in the \Windows folder of your device for msmqd.dll, which will indicate that you have the MSMQ runtimes. If you don't, then you will have to get them. The best place to look for them is in the Platform SDKs provided with eMbedded Visual Tools, which you can download from http://www.microsoft.com/mobile/downloads/emvt30.asp. After installation you will find the Platform SDKs in the Windows CE Tools folder, and the MSMQ runtimes will reside there. For example, you can find the files required for MSMQ for Pocket PC on ARM processors in the Windows CE Tools\wce300\MS Pocket PC\support\msmq\arm folder.
Figure 4 summarizes the files needed to implement the complete set of MSMQ services for Windows CE. After locating these files, copy all of them except visadm.exe to the \Windows folder on the device; copy visadm.exe to \Windows\Programs\MSMQ.
Install MSMQ Now that the required files exist on your device, you have three options for installing MSMQ for Windows CE. First, you can use msmqadm.exe at the command line. Second, you can add the appropriate registry entries yourself (MSMQ for Windows CE is completely configured within the Windows CE registry). Third, you can use the visadm utility. Although you may want to use msmqadm.exe or explicit registry editing if you are installing MSMQ services for Windows CE as part of a custom installation program, using visadm is definitely preferable in almost all situations because it provides a simple one-button install.
To install MSMQ using the visadm utility, simply run visadm.exe, click on the Shortcuts button, and a dialog will pop up. On the dialog, click the Install button and you're good to go. Visadm provides other helpful capabilities which you can read about in the "Administration Tools" sidebar.
Configure Registry Entries Registering MSMQ for Windows CE means placing the necessary registry keys and values into the registry to provide the base configuration for MSMQ for Windows CE. At first it may seem odd to you (like it did to me) that a base configuration isn't created as part of the install step or at least at the next boot. The reason that registration is left as an explicit user action is that a GUID is generated to identify the queue manager for Windows CE. Generating this GUID (as with all GUIDs) is dependent on the system clock and the MSMQ for Windows CE engineers don't want to assume you've correctly set the system time yet because an incorrectly set time can lead to more than one device with the same GUID. So first be sure that your computer's name and time are set correctly, then register MSMQ for Windows CE.
As I mentioned earlier, it is possible to create the necessary registry entries yourself if, for example, you are writing an application that includes MSMQ in its installation and you don't want to include administrative tools like visadm.exe and msmqadm.exe in the installation. However, MSMQ for Windows CE can be easily registered using the Register button on the Shortcuts dialog of Visadm. Since almost the entire persistent state for MSMQ for Windows CE is stored in the registry (except for queue and message data stored in the base directory) you'll spend a lot of time tweaking these entries as you experiment, so I suggest you become familiar with them (see Figure 5).
Note that netregd entries are not required in a static IP environment. You should also note that there are many more possible entries in an MSMQ configuration, but the ones shown here are the basic entries. You can use the remote registry editor found in the Tools menu of both eMbedded Visual Basic® and eMbedded C++ to access the registry on Windows CE. If you use this tool, you should be aware that it shows the registry for your desktop machine as My Computer. It's a common mistake to think you're looking at your Windows CE registry with this, especially if the registry editor doesn't automatically detect the device running Windows CE. In that case you will need to explicitly add a connection. Figure 6 shows the remote registry editor with the menu option for adding a connection and the entry for my handheld device.
Figure 6 Windows CE Regedit
Starting the MSMQ Device Driver is just as easy as you may have guessed. Just use the Start button on the Shortcuts dialog of visadm to load the MSMQ device driver. Nothing difficult here. If you want to know if MSMQ is really running on your device, you can use the Remote Process Viewer tool accessed from the Tools menu in both eMbedded Visual Basic or eMbedded Visual C++® to see if the msmqd.dll is displayed in the process list of your device. Figure 7 shows the Windows CE Remote Process Viewer tool with msmqd.dll listed in the bottom pane after selecting device.exe in the top pane.
Figure 7 Remote Process Viewer
Configure Name Resolution To enable MSMQ for Windows CE to send messages to queues on remote machines, you must configure a means for MSMQ for Windows CE to perform name resolution for those machines. You can do this in one of three ways: WINS, DNS, or a registry subkey on the device running Windows CE. If you are using WINS, then the netregd.dll that is part of the MSMQ for Windows CE installation will provide WINS registration and NetBIOS services. If you are using either DNS or a registry subkey, then netregd.dll is not required and can be disabled (it is enabled by default to load on boot-up) by removing the HKEY_LOCAL_MACHINE\Drivers\BuiltIn\NETREGD registry entry and rebooting the device. Note that although the documentation states that this registry entry is required, I found that MSMQ for Windows CE runs just fine without it. If you elect to use DNS, be aware that MSMQ for Windows CE only supports a DNS configuration of static IP addressing with reverse lookup enabled.
Unless you are comfortable with WINS and/or DNS, I suggest that you keep your first experimentation with MSMQ for Windows CE simple by using the registry subkey approach. To do this, add a subkey to HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts for each machine name that must be resolved, then add binary values for the IP address and expiration time. The following code shows a registry export of a key entry that will resolve the name "stargate" to IP address 184.108.40.206 (you should note the ExpireTime value, which indicates no expiration). After configuring this registry setting correctly, MSMQ for Windows CE will be able to resolve the machine name without having to reference to any external lookup service.
Now that you've got MSMQ for Windows CE up and running and understand how it's configured, you're probably anxious to start working with it. MSMQ for Windows CE exposes an API that can be used to develop a message queuing application on Windows CE, so let's take a look at it.
eMbedded Visual Tools 3.0 and the MSMQ for Windows CE API Using MSMQ for Windows CE in an application program means that at the most basic level you will be sending and receiving messages, so let's keep things simple and take a look at how you can write code to do just that. I won't dig into the details of the eMbedded Visual Tools, which you can find in Paul Yao's article "Windows CE: eMbedded Visual Tools 3.0 Provide a Flexible and Robust Development Environment" in the January 2001 issue of MSDN® Magazine.
The first thing you will notice about the MSMQ for Windows CE API is that, unlike its desktop relative, it has no COM wrapper for the C API. That means a programmer who uses Visual Basic and MSMQ on the desktop might write the following code using a QueueInfo object.
A developer working in eMbedded Visual Basic on Windows CE, on the other hand, will find no such object available. In light of this, the first thing I decided to do when exercising the API was to write a COM wrapper around the basic send and receive functions of the MSMQ for Windows CE API. Not only would this allow me to become familiar with the API, it would also provide a rudimentary COM object that could be used by some of my colleagues who wanted to experiment with eMbedded Visual Basic to write applications using MSMQ for Windows CE.
' Create a new QueueInfo object.
Set qinfo = New MSMQQueueInfo
' Set the pathname of the queue.
qinfo.PathName = ".\PRIVATE$\TestQueue"
' Set additional queue properties.
qinfo.Label = "Test Queue"
' Create the queue.
On Error GoTo ErrorHandler
MsgBox "Queue is created."
After writing a basic COM wrapper for simple sending and receiving, I discovered Ken Rabold's book Programming MSMQ on Pocket PC (MightyWords, 2000). The book focuses on writing Visual Basic-based programs with MSMQ on Windows CE and includes a complete COM wrapper for MSMQ for Windows CE that closely follows the desktop MSMQ object model.
Creating a Sample Project For those of you familiar with ATL in Visual C++, you will be glad to know that eMbedded Visual C++ includes the ATL COM AppWizard so you can easily create COM applications. It's virtually the same ATL wizard you've come to know and love in the desktop version of Visual C++, minus some features like MTS support and with an appropriate renaming to Windows CE ATL COM AppWizard.
To start things off, I used the ATL COM AppWizard to create a project named MessageServer, as shown in Figure 8. Note that when creating a project, eMbedded Visual C++ lets you choose from a range of target CPUs that are supported by Windows CE. You can select and deselect as appropriate for your build. Also note that AppWizard will allow you to support MFC, but the MessageServer project does not require it.
Figure 8 ATL COM AppWizard
The final step in setting up the project was to use the Project | Settings | Link tab to specify linking to msmqrt.lib in order to access the MSMQ for Windows CE library, as shown in Figure 9. The required MSMQ support files are located in the installation folders of the Platform SDK. For example, for Pocket PCs on ARM processors you will find msmqrt.lib in Windows CE Tools\wce300\MS Pocket PC\lib\arm, and you will find mq.h (which you will need to specify as an include in your code) in Windows CE Tools\wce300\MS Pocket PC\include.
Figure 9 Project Settings
After setting up my project, I inserted a new ATL Simple Object (yes, just like in desktop Visual C++!) called MsgMgr to create the class that would wrap my calls to the MSMQ for Windows CE API. I made sure to specify on the ATL Object Wizard Attributes tab that I wanted support for ISupportErrorInfo to build COM exception handling into my MSMQ wrapper.
Then (I'm getting closer to the MSMQ fun) I added a method called Send to IMsgMgr to serve as a wrapper method for the API calls required to send a message via MSMQ for Windows CE. I defined the Send method to accept the name of a destination queue for the message, a label for the message, the message itself, and an optional parameter indicating a queue to which receipt acknowledgments should be sent.
The following code is the IDL for the Send method:
Figure 10 shows the complete code for the method.
HRESULT Send([in] BSTR QueueName, [in] BSTR Label,
[in] BSTR Message, [in, optional] BSTR AckQueue)
Now let's take a walk through the Send method. First I established some property values that will be used when opening the queue to specify that I am opening for SEND access and that the sharing mode of the queue during this open state should be DENY_NONE to avoid "locking" the queue from use by other applications during my send. Note that when I specify the queue name I do so by referencing the "QueueName" parameter passed into the method by the caller.
MQOpenQueue is then called to open the queue. All of this is shown in Figure 11. Notice that a pointer to a QUEUEHANDLE is passed and that a valid queue handle is returned if the open is successful. Also notice that the queue name passed in the call to MQOpenQueue is a queue format name. This deserves a small digression on how queues can be referenced.
Referencing Queues in Code Message queues can be referenced in three ways: by path name, by queue handle, and by format name. A path name is used only when you are creating a queue and, as the name implies, is really telling MSMQ where in the MSMQ base directory to store the messages belonging to the queue. Path names are specified in the form MachineName\QueueName, where QueueName will result in the creation of a file name in the form QueueName.iq for storing the messages residing in the queue. As I mentioned earlier, queues and messages are persisted in file stores in the location specified by the HKEY_LOCAL_MACHINE\Software\Microsoft\MSMQ\SimpleClient\BaseDir registry entry (as shown in Figure 5).
A queue handle is returned to an application when it opens a queue. While the queue is open, the application uses the handle of the queue to perform functions such as send and receive.
Format names are used when referencing a queue to perform an operation. They come in several varieties, of which Direct format names are the most important to MSMQ for Windows CE. Direct refers to the fact that you are directly addressing the queue by telling MSMQ to use the information provided in the format name for locating the queue rather than looking it up in a directory service. Remember that MSMQ for Windows CE does not support dependent client functionality, so it is important to understand direct format names since you will use them often.
Direct format names are specified in the form DIRECT=AddressSpecification\QueueName (for public queues) and DIRECT=AddressSpecification\PRIVATE$\QueueName (for private queues). AddressSpecification in this case refers to either the network protocol (Message Queuing supports TCP and SPX) followed by the network address of the target machine, or to the operating system protocol followed by any string supported by the underlying operating system that identifies the target machine. Here are some examples using direct format names to reference queues when using MSMQ for Windows CE:
I've seen lots of posts in newsgroups from people wondering how the MSMQ for Windows CE documentation references to an OutFRS queue fits into all this, so I should briefly mention something about it here. An OutFRS queue can be referenced in an OutFRSQueue registry entry in HKEY_LOCAL_MACHINE\Software\Microsoft\MSMQ\SimpleClient. An OutFRS queue is an outgoing queue, in direct name format, that points to a Falcon Routing Server (FRS) which can route messages to their final destination. This is a way to route messages to public queues if you don't know the name of the machine on which the queue resides. You can think of this capability as something of a substitute for the dependent client functionality that MSMQ for Windows CE does not support. If you stick with direct format names, then you don't need an OutFRS registry entry. I suggest that to keep your first experiences with MSMQ as simple as possible you should stick with referencing queues by using direct format names and avoid using an OutFRS queue.
DIRECT=TCP:220.127.116.11\MyQueue // using a network address
DIRECT=OS:MyMachine\MqQueue // an OS reference to a public queue
// OS reference to private queue
Constructing a Message Now back to the code. If a valid queue format name such as DIRECT=OS:MyMachine\PRIVATE$\MyQueue, access mode, and sharemode have been passed, then the call to MQOpenQueue will be successful and a queue handle will be returned. The queue handle will be used in a call to the MQSendMessage function when sending the message, but first an MQMSGPROPS structure must be populated to hold the message properties (which include the message content itself).
In the following declarations MsgProps is the MQMSGPROPS structure that will contain the message properties. An MQMSGPROPS structure holds references to two other structures: MSGPROPID and PROPVARIANT. The code declares aMPropId as the MSGPROPID, which is an array containing the identifiers of the properties being set in this MQMSGPROPS structure. You can also see that aMVariant is declared as PROPVARIANT, which is an array of MQPROPVARIANT structures which themselves are nothing more than Variant structures holding the property values and data types.
The following code is an example of how to load these structures to specify a property, in this case the message label:
DWORD MPropIdCount = 0;
You can see that aMPropId is set to tell MSMQ for Windows CE that I am setting the label property. The vt member of the corresponding aMVariant array element is then set to specify the data type of the label value, and the pwszVal member is set to the actual label value (in this case the value that was passed in via the Label parameter of the Send method). The use of aMVariant should look very familiar to anyone who has used Variant structures in other settings.
aMPropId[MPropIdCount] = PROPID_M_LABEL; // Prop identifier
aMVariant[MPropIdCount].vt = VT_LPWSTR; // Type indicator
aMVariant[MPropIdCount].pwszVal = Label; // Queue label
In a similar fashion I set the message body to the Message value passed to the Send method, and indicate the data type of the message body in the code in Figure 12. Then I check for the optional parameter of the Send method, AckQueue, which is passed by the caller if an acknowledgment of receipt is required. This is shown in Figure 13 where I check to see if the value was passed. If it was, I set message properties to specify that I want an acknowledgment posted when the message reaches the queue, and to what queue the acknowledgment should be directed. Now that I have finished populating the message property structures, I can point the MQMSGPROPS structure to them in the following code:
// Set the MQMSGPROPS structure
MsgProps.cProp = MPropIdCount; // Number of properties.
MsgProps.aPropID = aMPropId; // Ids of properties.
MsgProps.aPropVar = aMVariant; // Values of properties.
MsgProps.aStatus = NULL; // No Error report.
Sending the Message At this point I can use the handle I am holding to the opened queue and call MQSendMessage as follows, supplying the name of the target queue and a pointer to the MQMSGPROPS structure.
You can reference the code listing for the Send method (shown in Figure 10) to see that the remainder of the Send implementation is simple error handling and a call to MQCloseQueue, passing it the queue handle to close the queue. The code for the receive function is very similar to the Send method in that it relies on the MQMSGPROPS structure, except that in this case I am popping a message off the queue (using a call to MQReceiveMessage), using the MQMSGPROPS values to indicate what properties I want to extract from the message, and using [in, out] parameters to return the message label and message body to the caller. Because of the similarity between the two functions, you can download the code for the receive function from the link at the top of this article.
// Send message
hr = MQSendMessage(
hQueue, // handle to the Queue.
&MsgProps, // Message properties to be sent.
NULL // No transaction.
Moving on from Here This article has introduced the basics of installing and configuring MSMQ for Windows CE and working with its API. In the sample code accompanying this article, you will find an eMbedded Visual Basic client application that exercises the Send method of the eMbedded Visual C++ code discussed in this article (the full source can be downloaded). Figure 14 shows this sample application running on a Windows CE-based device (Pocket PC).
Figure 14 Sample App
You may want to modify the sample eMbedded Visual Basic client code to pass an acknowledgment queue to the Send method, or extend it to exercise the Receive method to read messages sent from a server. Note that in both cases you will need to first use the MQCreateQueue function of the MSMQ for Windows CE API to create the local queue on the device running Windows CE to which the remote server will send messages. You could then write a bit of code for your server to process and reply to messages sent from your client. At that point, you'll have the basics in place for experimenting with integrating your mobile Windows CE-based devices with your server infrastructure via round-trip, reliable messaging using MSMQ for Windows CE.