bool CMsmqWarpper::CreatePublicQueue(LPCWSTR wszPathName) { if (wszPathName == NULL) { return false; } HRESULT hr = MQ_OK; //只设置一个属性,路径 const int NUM_PROPERTIES = 1; MQQUEUEPROPS QueueProps; MQPROPVARIANT aQueuePropVar[NUM_PROPERTIES]; QUEUEPROPID aQueuePropId[NUM_PROPERTIES]; HRESULT aQueueStatus[NUM_PROPERTIES]; int nPropIds = 0; aQueuePropId[nPropIds] = PROPID_Q_PATHNAME; aQueuePropVar[nPropIds].vt = VT_LPWSTR; aQueuePropVar[nPropIds].pwszVal = (LPWSTR)wszPathName; nPropIds++; QueueProps.cProp = nPropIds; QueueProps.aPropID = aQueuePropId; QueueProps.aPropVar = aQueuePropVar; QueueProps.aStatus = aQueueStatus; DWORD dwFormatNameBufferLength = 0; hr = MQCreateQueue(NULL, &QueueProps, NULL, &dwFormatNameBufferLength); // 如果创建成功或者队列已经存在,认为正确 if (hr == MQ_OK || hr == MQ_ERROR_QUEUE_EXISTS || hr == MQ_INFORMATION_FORMATNAME_BUFFER_TOO_SMALL) { return true; } return false; }
//-------------------------------------------------------- // // 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::OpenPrivateReceiveQueue() { // // Compose the pathname to the receiving queue and make it private. // 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), "private$"); strcat_s(mbsPathName, sizeof(mbsPathName), "\\"); strcat_s(mbsPathName, sizeof(mbsPathName), m_strLogin); // // Prepare the properties of the receiving queue. // 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. // WCHAR wcsFormatName[MAX_FORMAT_NAME_LEN+1]; dwNumChars = sizeof(wcsFormatName)/sizeof(wcsFormatName[0]); HRESULT hr = MQCreateQueue(NULL, &propsQueue, wcsFormatName, &dwNumChars); if (FAILED(hr) && hr != MQ_ERROR_QUEUE_EXISTS) { return FALSE; } if( hr == MQ_ERROR_QUEUE_EXISTS) { // // If the receiving queue already exists, obtain its format name. // WCHAR wcsLoginName[MQ_MAX_Q_NAME_LEN+1]; nResultedStringLength=0; mbstowcs_s( &nResultedStringLength, wcsLoginName, sizeof(wcsLoginName)/sizeof(wcsLoginName[0]), m_strLogin, sizeof(wcsLoginName)/sizeof(wcsLoginName[0])-1 ); swprintf_s(wcsFormatName, sizeof(wcsFormatName)/sizeof(wcsFormatName[0]), L"DIRECT=OS:.\\private$\\%s",wcsLoginName); } // // Open the receiving queue (a local private queue). // hr = MQOpenQueue(wcsFormatName, MQ_RECEIVE_ACCESS, MQ_DENY_NONE , &m_hqIncoming); if (FAILED(hr)) { return FALSE; } return TRUE; }
HRESULT MsmqQueue::createQueue( const char *szQueuePath, const char *szQueueLabel, bool isTransactional ) { HRESULT hr = MQ_OK; int len; // example: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msmq/msmq_using_createqueue_0f51.asp const int NUMBEROFPROPERTIES = 5; MQQUEUEPROPS QueueProps; MQPROPVARIANT aQueuePropVar[NUMBEROFPROPERTIES]; QUEUEPROPID aQueuePropId[NUMBEROFPROPERTIES]; HRESULT aQueueStatus[NUMBEROFPROPERTIES]; DWORD i = 0; if (szQueuePath == NULL) return MQ_ERROR_INVALID_PARAMETER; WCHAR wszPathName[MQ_MAX_Q_NAME_LEN] = {0}; len= strlen(szQueuePath); if (MultiByteToWideChar( CP_ACP, 0, szQueuePath, len, wszPathName, _countof( wszPathName ) ) == 0) { return MQ_ERROR_INVALID_PARAMETER; } if (len < _countof( wszPathName ) ) wszPathName[len]= 0; // need this to terminate WCHAR wszLabel[MQ_MAX_Q_LABEL_LEN] = {0}; len= strlen(szQueueLabel); if (MultiByteToWideChar( CP_ACP, 0, szQueueLabel, len, wszLabel, _countof( wszLabel ) ) == 0) { return MQ_ERROR_INVALID_PARAMETER; } if (len < _countof( wszLabel ) ) wszLabel[len]= 0; // need this to terminate printf("attempting to create queue with name= '%S', label='%S'\n", wszPathName, wszLabel); // Set the PROPID_Q_PATHNAME property with the path name provided. aQueuePropId[i] = PROPID_Q_PATHNAME; aQueuePropVar[i].vt = VT_LPWSTR; aQueuePropVar[i].pwszVal = wszPathName; // wszActualName i++; // Set optional queue properties. PROPID_Q_TRANSACTIONAL // must be set to make the queue transactional. aQueuePropId[i] = PROPID_Q_TRANSACTION; aQueuePropVar[i].vt = VT_UI1; aQueuePropVar[i].bVal = (unsigned char) isTransactional; i++; // aQueuePropId[i] = PROPID_Q_LABEL; aQueuePropVar[i].vt = VT_LPWSTR; aQueuePropVar[i].pwszVal = wszLabel; i++; // Initialize the MQQUEUEPROPS structure QueueProps.cProp = i; //Number of properties QueueProps.aPropID = aQueuePropId; //IDs of the queue properties QueueProps.aPropVar = aQueuePropVar; //Values of the queue properties QueueProps.aStatus = aQueueStatus; //Pointer to return status // http://msdn.microsoft.com/library/en-us/msmq/msmq_ref_functions_8dut.asp WCHAR wszFormatName[MQ_MAX_Q_NAME_LEN] = {0}; DWORD dwFormatNameLength = _countof(wszFormatName); hr = MQCreateQueue(NULL, // Security descriptor &QueueProps, // Address of queue property structure wszFormatName, // Pointer to format name buffer &dwFormatNameLength); // Pointer to receive the queue's format name length return 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; }