MQSendMessage возвращает S_OK, даже если сообщение не отправлено - PullRequest
0 голосов
/ 10 ноября 2019

MQSendMessage () возвращает значение S_OK, даже если сообщение не отправлено. Есть ли способ, чтобы убедиться, что сообщение было отправлено?

В соответствии с ограничение хранилища для очереди сообщений в одной очереди не работает? функция всегда будет возвращать S_OK (если не возникает очевидная ошибкакак неправильные параметры), даже если сообщение не может быть отправлено.

1 Ответ

0 голосов
/ 10 ноября 2019

Из документации для MQSendMessage:

Информация об ошибках, возникающих после помещения сообщения в исходящую очередь, предоставляется сообщениями подтверждения.

API ожидает, что вы запросите подтверждающее сообщение, получите его позже и сопоставите его с оригиналом, используя свое свойство PROPID_M_CORRELATIONID. На этой странице приведен пример:

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms700122%28v%3dvs.85%29

РЕДАКТИРОВАТЬ: По ссылке:

HRESULT MatchAck(  
                 LPCWSTR wszAdminQueueName,   
                 LPCWSTR wszComputerName,  
                 UCHAR * rgucMsgID                    //Array of bytes  
                 )  
{  

  // Validate the input strings.  
  if (wszAdminQueueName == NULL || wszComputerName == NULL)  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  

  //  Define the required constants and variables.  
  const int NUMBEROFPROPERTIES = 3;                   // Number of properties  
  DWORD cPropId = 0;                                  // Property counter  
  WCHAR wszLabelBuffer[MQ_MAX_MSG_LABEL_LEN];         // Message label buffer  

  // Define an MQMSGPROPS structure.  
  MQMSGPROPS msgprops;  
  MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];  
  PROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];  
  HRESULT aMsgStatus[NUMBEROFPROPERTIES];  

  HANDLE hQueue = NULL;                               // Queue handle  
  HANDLE hCursor = NULL;                              // Cursor handle  
  HRESULT hr = MQ_OK;                                 // Return code  
  int i = 0;                                          // Array index  

  // Create a buffer of unsigned characters of length   
  // PROPID_M_CORRELATIONID_SIZE, which is equal to 20, and specify   
  // PROPID_M_CORRELATIONID as a message property to be retrieved.  
  UCHAR rgucCorrelationID[PROPID_M_CORRELATIONID_SIZE];  

  aMsgPropId[cPropId] = PROPID_M_CORRELATIONID;       // Property ID  
  aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1 ;      // Type indicator  
  aMsgPropVar[cPropId].caub.pElems = rgucCorrelationID;  
  aMsgPropVar[cPropId].caub.cElems = PROPID_M_CORRELATIONID_SIZE;  
  cPropId++;  

  // Specify the message label and its length as message properties to be retrieved.  
  aMsgPropId[cPropId] = PROPID_M_LABEL_LEN;           // Property ID  
  aMsgPropVar[cPropId].vt = VT_UI4;                   // Type indicator  
  aMsgPropVar[cPropId].ulVal = MQ_MAX_MSG_LABEL_LEN;  // Label buffer size  
  cPropId++;  

  aMsgPropId[cPropId] = PROPID_M_LABEL;               // Property ID  
  aMsgPropVar[cPropId].vt = VT_LPWSTR;                // Type indicator  
  aMsgPropVar[cPropId].pwszVal = wszLabelBuffer;      // Label buffer  
  cPropId++;  

  // Initialize the MQMSGPROPS structure.  
  msgprops.cProp = cPropId;                           // Number of message properties  
  msgprops.aPropID = aMsgPropId;                      // IDs of the message properties  
  msgprops.aPropVar = aMsgPropVar;                    // Values of the message properties  
  msgprops.aStatus  = aMsgStatus;                     // Error reports  

  // Generate the format name required for opening the administration queue.  
  WCHAR * wszAdminFormatName = NULL;  
  DWORD dwFormatNameLength = 0;  
  dwFormatNameLength = wcslen(wszAdminQueueName) + wcslen(wszComputerName) + 12;  
  wszAdminFormatName = new WCHAR[dwFormatNameLength];  
  if (wszAdminFormatName == NULL)  
  {  
    return MQ_ERROR_INSUFFICIENT_RESOURCES;  
  }  
  memset(wszAdminFormatName, 0, dwFormatNameLength*sizeof(WCHAR));  

  // ************************************  
  // You must concatenate "DIRECT=OS:", wszComputerName, "\",        
  // and wszAdminQueueName into the wszAdminFormatName buffer.  
  // wszAdminFormatName = "DIRECT=OS:" + wszComputerName + "\" +        
  // wszAdminQueueName  
  // If the format name is too long for the buffer,  
  // return FALSE.  
  // ************************************  

  // Open the administration queue to peek at all the messages.  
  hr = MQOpenQueue(  
                   wszAdminFormatName,                // Format name of the administration queue  
                   MQ_RECEIVE_ACCESS,                 // Access mode  
                   MQ_DENY_RECEIVE_SHARE,             // Share mode  
                   &hQueue                            // OUT: Queue handle  
                   );  

  // Free the memory that was allocated for the format name string.  
  delete [] wszAdminFormatName;  

  // Handle any error returned by MQOpenQueue.  
  if (FAILED(hr))  
  {  
    return hr;  
  }  

  // Create the cursor used to navigate through the administration queue.  
  hr = MQCreateCursor(  
                      hQueue,                         // Queue handle  
                      &hCursor                        // OUT: Cursor handle  
                      );  
  if (FAILED(hr))  
  {  
    MQCloseQueue(hQueue);  
    return hr;  
  }  

  // Peek at the first message in the administration queue.  
  hr = MQReceiveMessage(  
                        hQueue,                    // Queue handle  
                        0,                         // Maximum time (msec)  
                        MQ_ACTION_PEEK_CURRENT,    // Receive action  
                        &msgprops,                 // Message property structure  
                        NULL,                      // No OVERLAPPED structure  
                        NULL,                      // No callback function  
                        hCursor,                   // Cursor handle  
                        MQ_NO_TRANSACTION          // Not in a transaction  
                        );  
  if (FAILED(hr))  
  {  
    MQCloseCursor(hCursor);  
    MQCloseQueue(hQueue);  
    return hr;  
  }  

  // Find the matching message in the administration queue.  
  do  
  {  
    for (i = 0; (rgucMsgID[i] == rgucCorrelationID[i]) && (i < 20); i++);  
    if (i == 20)                                   // The message and correlation IDs match.  
    {  

      // Display the label of the message.  
      wprintf(L"Label of the matching message: %s\n", msgprops.aPropVar[2].pwszVal);   

    }  

    //Peek at the next message in the administration queue.  
    hr = MQReceiveMessage(  
                          hQueue,                 // Queue handle  
                          0,                      // Maximum time (msec)  
                          MQ_ACTION_PEEK_NEXT,    // Receive action set to peek at the next message  
                          &msgprops,              // Message property structure  
                          NULL,                   // No OVERLAPPED structure  
                          NULL,                   // No callback function  
                          hCursor,                // Cursor handle  
                          NULL                    // No transaction  
                          );  
    if (FAILED(hr))  
    {  
      break;  
    }  

  } while (SUCCEEDED(hr));  

  // Close the cursor and queue to free resources.  
  hr = MQCloseCursor(hCursor);  
  if (FAILED(hr))  
  {  
    MQCloseQueue(hQueue);  
    return hr;  
  }  

  hr = MQCloseQueue(hQueue);  
  if (FAILED(hr))  
  {  
    return hr;  
  }  
  wprintf(L"Peeking completed! Label of the last message: %s\n", msgprops.aPropVar[2].pwszVal);   
  return hr;  
}  
...