Подтвердить что ты не робот

Ошибка очереди сообщений: не удается найти форматировщик, способный читать сообщение

Я пишу сообщения в очередь сообщений в С# следующим образом:

queue.Send(new Message("message"));

Я пытаюсь прочитать сообщения следующим образом:

Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
  String message = m.Body;
  //do something with string
}

Однако я получаю сообщение об ошибке, в котором говорится: "Невозможно найти форматировщик, способный читать это сообщение".

Что я делаю неправильно?

4b9b3361

Ответ 1

Я решил проблему, добавив форматтер для каждого сообщения. Добавление форматирования в очередь не сработало.

Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
  m.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
  String message = m.Body;

  //do something with string
}

Ответ 2

Или вы можете использовать

 message.Formatter =
     new System.Messaging.XmlMessageFormatter(new Type[1] { typeof(string) });

Ответ 3

вы можете попробовать прочесть боди-поток сообщения вместо тела, например:

StreamReader sr = new StreamReader(m.BodyStream);    
string messageBody = "";    
while (sr.Peek() >= 0) 
{
    messageBody += sr.ReadLine();
}

Ответ 4

Кажется, что сериализация выполняется только при доступе к свойству Body класса Message. До тех пор, пока вы получаете доступ к свойству Body после того, как вы установите на сообщение, правильный Formatter работает нормально.

Если вы предпочитаете не создавать Formatter для каждого сообщения, вы можете установить Formatter в очереди, и для каждого сообщения (перед доступом к свойству Body) установите свойство Formatter из Formatter очереди.

_queue.Send(new Message() { Formatter = _queue.Formatter, Body = myData } );

var msg = _qeueu.Receive();
msg.Formatter = _queue.Formatter;
var myObject = (MyClass) msg.Body;

Ответ 5

Все здесь проделали фантастическую работу по предоставлению решений, и, только что закончив борьбу с этой проблемой, я хотел бросить свой собственный 2c и показать, какое решение я придумал, это работает очень хорошо.

Во-первых, когда очередь создается, я убеждаюсь, что я открываю такие разрешения (я не беспокоюсь о безопасности очередей в контексте нашего приложения... это вычисленное решение):

queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);

Без этой строки я получал бы всевозможные недостижимые ошибки и даже не мог просматривать очередь с экрана управления компьютером. Кстати, если это происходит с вами, и вам интересно, как убить очередь, в которой у вас нет доступа:

  • Остановить службу "Очередь сообщений"
  • Перейти к "C:\Windows\System32\msmq\storage\lqs"
  • Откройте каждый файл в блокноте и найдите имя очереди (скорее всего, это файл, который был недавно изменен)
  • Удалите этот файл и перезапустите службу обмена сообщениями

Создайте базовый класс для ваших сообщений в очереди и отметьте его [Serializable]. В кеше загрузки приложений список всех типов сообщений используется примерно так:

var types = typeof(QueueItemBase).Assembly
            .GetTypes()
            .Where(t => typeof(QueueItemBase).IsAssignableFrom(t) && t.IsAbstract == false)
            .ToArray();
...
// Create and cache a message formatter instance
_messageFormatter = new XmlMessageFormatter(types);

Теперь вы готовы начать получать сообщения. Мой первый инстинкт состоял в том, чтобы опросить сообщения, но api не очень нравится работать именно так. Поэтому я создаю фоновый поток и вызываю метод блокировки. Получаю в очереди, которая будет возвращаться после получения сообщения. Оттуда декодирование сообщения так же просто, как:

var message = queue.Receive();
if (message == null)
    continue;

// Tell the message about our formatter containing all our message types before we 
// try and deserialise
message.Formatter = _messageFormatter;

var item = message.Body as QueueItemBase;

И это должно быть все, что вам нужно для того, чтобы получить красиво реализованную, типичную интеграцию с MSMQ!

Ответ 6

Message recoverableMessage = new Message();
recoverableMessage.Body = "Sample Recoverable Message";

recoverableMessage.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib" });

MessageQueue myQueue = new MessageQueue(@".\private$\teste");

В очереди также должен быть установлен Formatter.

myQueue.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });

Ответ 7

это работает очень хорошо:

static readonly XmlMessageFormatter f = new XmlMessageFormatter(new Type[] { typeof(String) });

private void Client()
{
    var messageQueue = new MessageQueue(@".\Private$\SomeTestName");

    foreach (Message message in messageQueue.GetAllMessages())
    {
        message.Formatter = f;
        Console.WriteLine(message.Body);
    }
    messageQueue.Purge();
}

Ответ 8

Это помогло мне прочитать приватную очередь с удаленной машины:

MessageQueue queue = new MessageQueue(@"FormatName:Direct=OS:MACHINENAME\private$\MyQueueName", QueueAccessMode.Peek);

Message msg = queue.Peek();
StreamReader sr = new StreamReader(msg.BodyStream);
string messageBody = sr.ReadToEnd();

Ответ 9

Добавление форматирования позволило решить мою проблему:

 public void ReceiveAsync<T>(MqReceived<T> mqReceived)
    {
        try
        {
            receiveEventHandler = (source, args) =>
            {
                var queue = (MessageQueue)source;
                using (Message msg = queue.EndPeek(args.AsyncResult))
                {
                    XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(T) });
                    msg.Formatter = formatter;
                    queue.ReceiveById(msg.Id);
                    T tMsg = (T)msg.Body;
                    mqReceived(tMsg);

                }
                queue.BeginPeek();
            };

            messageQueu.PeekCompleted += receiveEventHandler;
            messageQueu.BeginPeek();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

Вы можете увидеть пример кода и библиотеку msmq на github: https://github.com/beyazc/MsmqInt