bool CMsmqWarpper::OpenPublicQueue(LPCWSTR wszPathName, bool connecttype) { if (wszPathName == NULL) { return false; } HRESULT hr = MQ_OK; if (connecttype) { DWORD dwFormatNameBufferLength = 256; WCHAR wszFormatNameBuffer[256] = {0}; hr = MQPathNameToFormatName(wszPathName, wszFormatNameBuffer, &dwFormatNameBufferLength); if (FAILED(hr)) { return false; } hr = MQOpenQueue(wszFormatNameBuffer, MQ_SEND_ACCESS, MQ_DENY_NONE, &m_hQueue ); } else { hr = MQOpenQueue(wszPathName, MQ_SEND_ACCESS, MQ_DENY_NONE, &m_hQueue ); } if (FAILED(hr)) { return false; } return true; }
//-------------------------------------------------------- // // Receiver Mode // ------------- // The receiver side does the following: // 1. Creates a queue on the local computer // of type "guidMQTestType". // The queue is either public or private, depending // on the connection we want to establish. // 2. Opens the queue. // 3. In a loop, // receives messages // and prints the message body and message label. // 4. Cleans up handles. // 5. Deletes the queue from the directory service. // //-------------------------------------------------------- void Receiver(int dDirectMode) { MQQUEUEPROPS qprops; MQMSGPROPS msgprops; MQPROPVARIANT aPropVar[MAX_VAR]; QUEUEPROPID aqPropId[MAX_VAR]; MSGPROPID amPropId[MAX_VAR]; DWORD cProps; WCHAR wcsFormat[MAX_FORMAT]; UCHAR Buffer[MAX_BUFFER]; WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN+1]; WCHAR wcsPathName[MAX_FORMAT]; DWORD dwNumChars; QUEUEHANDLE qh; HRESULT hr; int nPos; printf("\nReceiver Mode on Machine: %s\n\n", mbsMachineName); // // Set properties to create a queue on the local computer. // cProps = 0; // Set the path name. if(dDirectMode == DIRECT) // Private queue path name { nPos = _snwprintf_s( wcsPathName, sizeof(wcsPathName)/sizeof(wcsPathName[0]), sizeof(wcsPathName)/sizeof(wcsPathName[0]) - 1, L"%S\\private$\\MSMQTest", mbsMachineName ); if(nPos < 0) { printf("The path name is too long for the buffer. Exiting...\n"); exit(1); } } else // Public queue path name { nPos = _snwprintf_s( wcsPathName, sizeof(wcsPathName)/sizeof(wcsPathName[0]), sizeof(wcsPathName)/sizeof(wcsPathName[0]) - 1, L"%S\\MSMQTest", mbsMachineName ); if(nPos < 0) { printf("The path name is too long for the buffer. Exiting...\n"); exit(1); } } aqPropId[cProps] = PROPID_Q_PATHNAME; aPropVar[cProps].vt = VT_LPWSTR; aPropVar[cProps].pwszVal = wcsPathName; cProps++; // Specify the service type GUID of the queue. // (This property will be used to locate all the queues of this type.) aqPropId[cProps] = PROPID_Q_TYPE; aPropVar[cProps].vt = VT_CLSID; aPropVar[cProps].puuid = &guidMQTestType; cProps++; // Add a descriptive label to the queue. // (A label is useful for administration through the MSMQ admin tools.) aqPropId[cProps] = PROPID_Q_LABEL; aPropVar[cProps].vt = VT_LPWSTR; aPropVar[cProps].pwszVal = L"Sample application of MSMQ SDK"; cProps++; // Create a QUEUEPROPS structure. qprops.cProp = cProps; qprops.aPropID = aqPropId; qprops.aPropVar = aPropVar; qprops.aStatus = 0; // // Create the queue. // dwNumChars = MAX_FORMAT; hr = MQCreateQueue( NULL, // IN: Default security &qprops, // IN/OUT: Queue properties wcsFormat, // OUT: Format name &dwNumChars); // IN/OUT: Size of the format name if (FAILED(hr)) { // // API failed, but not because the queue exists. // if (hr != MQ_ERROR_QUEUE_EXISTS) Error("MQCreateQueue failed", hr); // // The queue exist, so get its format name. // printf("The queue already exists. Open it anyway.\n"); if(dDirectMode == DIRECT) // It's a private queue, so we know its direct format name. { int n = _snwprintf_s( wcsFormat, sizeof(wcsFormat)/sizeof(wcsFormat[0]), sizeof(wcsFormat)/sizeof(wcsFormat[0]) - 1, L"DIRECT=OS:%s", wcsPathName); if(n < 0) { printf("The format name is too long for the buffer. Exiting...\n"); exit(1); } } else // It's a public queue, so we must get its format name from the DS. { dwNumChars = sizeof(wcsFormat)/sizeof(wcsFormat[0]); hr = MQPathNameToFormatName( wcsPathName, // IN: Queue path name wcsFormat, // OUT: Format name &dwNumChars); // IN/OUT: Size of the format name if (FAILED(hr)) Error("The format name cannot be retrieved", hr); } } // // Open the queue with receive access. // hr = MQOpenQueue( wcsFormat, // IN: Queue format name MQ_RECEIVE_ACCESS, // IN: Want to receive from queue 0, // IN: Allow sharing &qh); // OUT: Handle of open queue // // Things are a little bit tricky. MQCreateQueue succeeded, but in the // case of a public queue, this does not mean that MQOpenQueue // will succeed, because replication delays are possible. The queue is // registered in the DS, but it might take a replication interval // until the replica reaches the server that I am connected to. // To overcome this, open the queue in a loop. // // In this specific case, this can happen only if this program // is run on an MSMQ 1.0 backup server controller (BSC) or on // a client connected to a BSC. // To be totally on the safe side, we should have put some code // to exit the loop after a few retries, but this is just a sample. // while (hr == MQ_ERROR_QUEUE_NOT_FOUND) { printf("."); // Wait a bit. Sleep(500); // Retry. hr = MQOpenQueue(wcsFormat, MQ_RECEIVE_ACCESS, 0, &qh); } if (FAILED(hr)) Error("The queue cannot be opened", hr); // // Main receiver loop // if(dDirectMode == DIRECT) { printf("\n* Working in workgroup (direct) mode.\n"); } printf("\n* Waiting for messages...\n"); for(;;) { // // Set the message properties for reading messages. // cProps = 0; // Ask for the body of the message. amPropId[cProps] = PROPID_M_BODY; aPropVar[cProps].vt = VT_UI1 | VT_VECTOR; aPropVar[cProps].caub.cElems = sizeof(Buffer); aPropVar[cProps].caub.pElems = Buffer; cProps++; // Ask for the label of the message. amPropId[cProps] = PROPID_M_LABEL; aPropVar[cProps].vt = VT_LPWSTR; aPropVar[cProps].pwszVal = wcsMsgLabel; cProps++; // Ask for the length of the label of the message. amPropId[cProps] = PROPID_M_LABEL_LEN; aPropVar[cProps].vt = VT_UI4; aPropVar[cProps].ulVal = sizeof(wcsMsgLabel); cProps++; // Create a MSGPROPS structure. msgprops.cProp = cProps; msgprops.aPropID = amPropId; msgprops.aPropVar = aPropVar; msgprops.aStatus = 0; // // Receive the message. // hr = MQReceiveMessage( qh, // IN: Queue handle INFINITE, // IN: Time-out MQ_ACTION_RECEIVE, // IN: Read operation &msgprops, // IN/OUT: Message properties to retrieve NULL, // IN/OUT: No OVERLAPPED structure NULL, // IN: No callback NULL, // IN: No cursor NULL); // IN: Not part of a transaction if (FAILED(hr)) Error("MQReceiveMessage failed", hr); // // Display the received message. // printf("%S : %s\n", wcsMsgLabel, Buffer); // // Check for a request to end the application. // if (_stricmp(Buffer, "quit") == 0) break; } /* while (1) */ // // Cleanup: Close the handle to the queue. // MQCloseQueue(qh); // // In the concluding stage, we delete the queue from the directory // service. (We don't need to do this. In case of a public queue, // leaving it in the DS enables sender applications to send messages // even if the receiver is not available.) // hr = MQDeleteQueue(wcsFormat); if (FAILED(hr)) Error("The queue cannot be deleted", hr); }
BOOL CDisdrawDlg::OpenReceiveQueue() { // // Do not create the receiving queue if it already exists in the enterprise. // HRESULT hr; WCHAR wcsFormatName[MAX_FORMAT_NAME_LEN+1]; if (!LocateQueue(m_strLogin, wcsFormatName, sizeof(wcsFormatName)/sizeof(wcsFormatName[0]))) { // // Form the pathname of the receiving queue. // char mbsPathName[MQ_MAX_Q_NAME_LEN+1]; DWORD dwNumChars = sizeof(mbsPathName); GetComputerName(mbsPathName, &dwNumChars); strcat_s(mbsPathName, sizeof(mbsPathName), "\\"); strcat_s(mbsPathName, sizeof(mbsPathName), m_strLogin); // // Prepare the receiving queue properties. // DWORD cProps = 0; QUEUEPROPID aPropId[3]; MQPROPVARIANT aPropVar[3]; MQQUEUEPROPS propsQueue; WCHAR wcsPathName[MQ_MAX_Q_NAME_LEN+1]; size_t nResultedStringLength=0; mbstowcs_s( &nResultedStringLength, wcsPathName, sizeof(wcsPathName)/sizeof(wcsPathName[0]), mbsPathName, sizeof(wcsPathName)/sizeof(wcsPathName[0])-1 ); aPropId[cProps] = PROPID_Q_PATHNAME; aPropVar[cProps].vt = VT_LPWSTR; aPropVar[cProps].pwszVal = wcsPathName; cProps++; aPropId[cProps] = PROPID_Q_TYPE; aPropVar[cProps].vt = VT_CLSID; aPropVar[cProps].puuid = &guidDrawType; cProps++; WCHAR wcsLabel[MQ_MAX_Q_LABEL_LEN+1]; nResultedStringLength=0; mbstowcs_s( &nResultedStringLength, wcsLabel, sizeof(wcsLabel)/sizeof(wcsLabel[0]), m_strLogin, sizeof(wcsLabel)/sizeof(wcsLabel[0])-1 ); aPropId[cProps] = PROPID_Q_LABEL; aPropVar[cProps].vt = VT_LPWSTR; aPropVar[cProps].pwszVal = wcsLabel; cProps++; propsQueue.cProp = cProps; propsQueue.aPropID = aPropId; propsQueue.aPropVar = aPropVar; propsQueue.aStatus = NULL; // // Create the receiving queue. // dwNumChars = sizeof(wcsFormatName)/sizeof(wcsFormatName[0]); hr = MQCreateQueue(NULL, &propsQueue, wcsFormatName, &dwNumChars); // // If the receiving queue already exists, obtain its format name. // if (hr == MQ_ERROR_QUEUE_EXISTS) { dwNumChars = sizeof(wcsFormatName)/sizeof(wcsFormatName[0]); hr = MQPathNameToFormatName(wcsPathName, wcsFormatName, &dwNumChars); } if (FAILED(hr)) return FALSE; } // // Open the receiving queue (it may be necessary to retry due to replication latency). // int iCount = 0; while ((hr = MQOpenQueue(wcsFormatName, MQ_RECEIVE_ACCESS, MQ_DENY_NONE , &m_hqIncoming)) == MQ_ERROR_QUEUE_NOT_FOUND) { Sleep (500); iCount++; if (iCount >=30) { // // A period of 15 seconds past without locating the queue. // We allow the user to stop attempts to open the queue. // int iRes = MessageBox("The receiving queue was not located.\nDo you want to continue searching?", NULL, MB_YESNO); if(iRes == IDYES) { // // Continue searching. // iCount =0; } else { // // Stop searching. // break; } } } if (FAILED(hr)) return FALSE; return TRUE; }