Sending Messages from Windows CE

< BACK  NEXT >
[oR]

Windows CE does not provide an object model for accessing MSMQ, so API calls need to be used. To use these API functions you will need to include mq.h and add the library msmqrt.lib to your project. A queue must first be opened, and then messages can be added to the queue. Finally, you will need to close the queue.

There are two ways in which a queue's name and location can be specified:

  • Format name A string that contains information about how the queue is named, the DNS computer on which it is located, the type of queue (for example, private or public), and the queue's name.

  • Path name A string that specifies the queue based only on the DNS, the queue type (private or public), and the queue's name.

An example of a format name to be used with Windows CE would be the following:

 DIRECT=OS:mycomputer\Private$\WinCEQueue 

This specifies a private queue on a computer with the DNS name "mycomputer", and with the queue name "WinCEQueue". The "DIRECT=OS" specification indicates that the computer should be resolved using DNS. Other "DIRECT" options allow the computer to be specified by IP address, but this is not supported in Windows CE. The "mycomputer" DNS name is the name of the Windows 2000 computer used when creating the queue, as described in the previous section, "Reading Messages from a Queue in Windows 2000."

An example of a path name to be used with Windows CE would be as follows:

 mycomputer\Private$\WinCEQueue 

This specifies the same queue as the format name example above. The MQOpenQueue function used to open a queue requires a format name, but it is often easier to work with path names. Therefore, the MQPathNameToFormatName function can be used to provide a conversion:

 TCHAR wszFormatName[256]; DWORD dwFormatNameLength = 256; hr = MQPathNameToFormatName     (_T("nickdell\\Private$\\WinCEQueue"),     wszFormatName,     &dwFormatNameLength); 

The function MQPathNameToFormatName is passed the path name to convert (the computer "nickdell" in this case is a Windows 2000 computer) and a string buffer in which the format name will be returned. The third parameter is a DWORD that contains the size of the buffer on calling the function and the number of characters in the format name on return.

Once the format name for the queue is obtained, the function MQOpenQueue (Table 15.1) can be called to open the queue. When opening a queue you must specify the type of access you need. For example, if you are reviewing the messages but not removing them, you can use MQ_PEEK_ACCESS. Otherwise, you may use MQ_SEND_ACCESS or MQ_RECEIVE_ACCESS to send and receive messages. A handle to the open queue is returned in a QUEUEHANDLE variable. The following code opens a queue for send access and does not deny other applications access to the queue:

 HRESULT hr; QUEUEHANDLE hq; hr = MQOpenQueue(wszFormatName,     MQ_SEND_ACCESS,     MQ_DENY_NONE,     &hq); 

Table 15.1. MQOpenQueue Opens queue on local or remote computer
MQOpenQueue
LPCWSTR lpwcsFormatName Format name of the queue.
DWORD dwAccess Type of access required to queue:
MQ_PEEK_ACCESS Messages will be read but not removed from queue.
MQ_SEND_ACCESS Messages will be sent to the queue.
MQ_RECEIVE_ACCESS Messages will be read and removed from the queue.
DWORD dwShareMode Access allowed to other applications using the queue:
MQ_DENY_NONE Allow other applications full access to the queue.
MQ_DENY_RECEIVE_SHARE Only allow other applications reading messages to access the queue.
LPQUEUEHANDLE phQueue Pointer to a queue handle variable in which the queue handle will be returned.
HRESULT Return Value MQ_OK on success, otherwise an error code.

The function MQSendMessage is used to send messages to an open queue. The function is passed a handle to an open queue, a pointer to a MQMSGPROPS structure describing the message to be sent, and a constant describing the transaction options to be used. NULL for the last parameter specifies that no transactions will be used.

 hr = MQSendMessage(hq,     &msgprops,     NULL); 

Most of the work in sending messages involves forming the MQMSGPROPS structure that describes the message options and data to be sent. To send a message you will need to provide the following properties:

  • PROPID_M_LABEL A textual description describing the message. You are free to provide any textual label. This can be used by the recipient application to decide how to process the message.

  • PROPID_M_BODY_TYPE A property describing the type of data contained in the message, for example, VT_BSTR for BSTR data.

  • PROPID_M_BODY A property describing the message's data and the data itself.

To create and initialize a MQMSGPROPS, you will first need to declare a MQMSGPROPS structure. You will then need to declare a MSGPROPID array to store the property identifiers (such as PROPID_M_LABEL), a PROPVARIANT array that will contain the property data, and an optional HRESULT array used forreturning error information associated with a property. The PROPVARIANT structure is used like the VARIANT structure described in Chapter 14 (COM and ActiveX). The "vt" member contains a constant that describes the data type (such as VT_LPWSTR for a null-terminated string), and a union member that refers to the data (such as pwszVal that points to a string). In the following code, a MQMSGPROPS structure is initialized ready to store information on three properties.

 MQMSGPROPS msgprops; MSGPROPID aMsgPropId[3]; MQPROPVARIANT aMsgPropVar[3]; HRESULT aMsgStatus[3]; msgprops.cProp = 3;             // Number of properties msgprops.aPropID = aMsgPropId;  // Ids of properties msgprops.aPropVar = aMsgPropVar;// Values of properties msgprops.aStatus = aMsgStatus;  // Error reports 

The PROPID_M_LABEL property contains a string for the message's label. The data type for the data stored in the MQPROPVARIANT element is therefore VT_LPWSTR, and the pwszVal member points to the string data.

 aMsgPropId[0] = PROPID_M_LABEL; aMsgPropVar[0].vt = VT_LPWSTR; aMsgPropVar[0].pwszVal = _T("Test Message"); 

The PROPID_M_BODY_TYPE property describes the data type for the message's body data. The data associated with this property is an unsigned 4-byte integer (VT_UI4), and the data in the ulVal member contains a constant describing the data type. The following code describes a message where the body data is a BSTR:

 aMsgPropId[1] = PROPID_M_BODY_TYPE; aMsgPropVar[1].vt = VT_UI4; aMsgPropVar[1].ulVal = VT_BSTR; 

Finally, the PROPID_M_BODY property describes the data for the message. The initialization depends on the type of data to be sent. The following code allocates a BSTR and sets the property to use this BSTR as the message's data:

 BSTR bStr =   SysAllocString(_T("Body text for the message")); aMsgPropId[2] = PROPID_M_BODY; aMsgPropVar[2].vt = VT_VECTOR|VT_UI1; aMsgPropVar[2].caub.pElems = (LPBYTE)bStr; aMsgPropVar[2].caub.cElems =         SysStringByteLen(bStr); 

The data type VT_VECTOR | VT_UI1 specifies that the data is to be passed as a counted array (that is, an array with a given size). The caub.pElems member describes the length of the data, and caub.cElems points to the data itself. The code in Listing 15.1 shows opening a queue, initializing the properties, and sending the message using MQSendMessage. Finally, the queue is closed through a call to MQCloseQueue this function takes a single parameter that is the handle to the queue to close. This code will send a message to a queue that can be read by the Visual Basic code described in the section "Reading Messages from a Queue in Windows 2000."

Listing 15.1 Opening queue and sending a message
 #include <mq.h> // Add MSMQRT.LIB to project void DisplayOpenError(HRESULT hr) {   if(hr == MQ_ERROR_ACCESS_DENIED)         cout   _T("Don't have access rights")   endl;   else if(hr == MQ_ERROR_ILLEGAL_FORMATNAME)          cout   _T("Illegal Format Name")   endl;   else if(hr == MQ_ERROR_QUEUE_NOT_FOUND )         cout   _T("Queue not found")   endl;   else if(hr == MQ_ERROR_SERVICE_NOT_AVAILABLE )         cout   _T("Cannot connect to queue mgr")                endl;   else if(hr == MQ_ERROR_INVALID_PARAMETER )         cout   _T("Invalid Parameter")   endl;   else if(hr == MQ_ERROR_SHARING_VIOLATION )         cout   _T("Sharing violation")   endl;   else if(hr == MQ_ERROR_UNSUPPORTED_ACCESS_MODE )         cout   _T("Invalid access mode")   endl;   else if(hr ==         MQ_ERROR_UNSUPPORTED_FORMATNAME_OPERATION)         cout   _T("Invalid format name")   endl;   else         cout   _T("Unexpected Error")   endl; } void Listing15_1() {   HRESULT hr;   QUEUEHANDLE hq;   TCHAR wszFormatName[256];   DWORD dwFormatNameLength = 256;   hr = MQPathNameToFormatName       (_T("nickdell\\Private$\\WinCEQueue"),       wszFormatName,       &dwFormatNameLength);   cout   wszFormatName   endl;   hr = MQOpenQueue(wszFormatName,       MQ_SEND_ACCESS,       MQ_DENY_NONE,       &hq);   if(hr == MQ_OK)     cout   _T("Opened queue")   endl;   else   {     DisplayOpenError(hr);     return;   }   DWORD cPropId = 0;   MQMSGPROPS msgprops;   MSGPROPID aMsgPropId[4];   MQPROPVARIANT aMsgPropVar[4];   HRESULT aMsgStatus[4];   aMsgPropId[cPropId] = PROPID_M_LABEL;   aMsgPropVar[cPropId].vt = VT_LPWSTR;   aMsgPropVar[cPropId].pwszVal = _T("Test Message");   cPropId++;   aMsgPropId[cPropId] = PROPID_M_BODY_TYPE;   aMsgPropVar[cPropId].vt = VT_UI4;   aMsgPropVar[cPropId].bVal = VT_BSTR;   cPropId++;   BSTR bStr = SysAllocString(       _T("Body text for the message"));   aMsgPropId[cPropId] = PROPID_M_BODY;   aMsgPropVar[cPropId].vt = VT_VECTOR|VT_UI1;   aMsgPropVar[cPropId].caub.pElems = (LPBYTE)bStr;   aMsgPropVar[cPropId].caub.cElems =       SysStringByteLen(bStr);   cPropId++;   msgprops.cProp = cPropId;   msgprops.aPropID = aMsgPropId;   msgprops.aPropVar = aMsgPropVar;   msgprops.aStatus = aMsgStatus;   hr = MQSendMessage(hq,         &msgprops,         NULL);   if (FAILED(hr))     cout   _T("Could not send message")   endl;   else     cout   _T("Message queued")   endl;   MQCloseQueue(hq); } 

If the Windows CE device on which this code runs cannot access the Windows 2000 machine where WinCEQueue is located, the messages will be stored in a local temporary queue. When the queue can next be accessed (for example, when the Windows CE device connects using RAS), MSMQ will automatically transfer the messages to the queue.


< BACK  NEXT >


Windows CE 3. 0 Application Programming
Windows CE 3.0: Application Programming (Prentice Hall Series on Microsoft Technologies)
ISBN: 0130255920
EAN: 2147483647
Year: 2002
Pages: 181

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net